检查蟒蛇类属性 [英] Inspect python class attributes

查看:149
本文介绍了检查蟒蛇类属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一种方法来检查的一类,所以我可以放心地识别哪些属性是用户定义的类属性。问题是,像迪尔(),inspect.getmembers(功能)和朋友返回所有类的属性,包括pre-定义那些诸如 __类__ __ __ DOC __ __字典 __ __哈希。这当然是可以理解的,人们可以说,我只能命名的成员名单忽视,但遗憾的是这些pre定义的属性也必然不同版本的Python的改变,因此让我的项目volnerable在改变蟒蛇项目 - 我不喜欢

I need a way to inspect a class so I can safely identify which attributes are user-defined class attributes. The problem is that functions like dir(), inspect.getmembers() and friends return all class attributes including the pre-defined ones like: __class__, __doc__, __dict__, __hash__. This is of course understandable, and one could argue that I could just make a list of named members to ignore, but unfortunately these pre-defined attributes are bound to change with different versions of Python therefore making my project volnerable to changed in the python project - and I don't like that.

例如:

>>> class A:
...   a=10
...   b=20
...   def __init__(self):
...     self.c=30
>>> dir(A)
['__doc__', '__init__', '__module__', 'a', 'b']
>>> get_user_attributes(A)
['a','b']

在上述我希望有一个安全的方式只提取用户定义的类属性['一','B']不'c'的,因为它是一个实例属性的例子。所以我的问题是......谁能帮助我与上述虚构功能 get_user_attributes(CLS)

In the example above I want a safe way to retrieve only the user-defined class attributes ['a','b'] not 'c' as it is an instance attribute. So my question is... Can anyone help me with the above fictive function get_user_attributes(cls)?

P.S。我花了一些时间,试图通过解析AST水平的类,它会很容易解决的问题。但我不能找到一种方法来解析已经物体转换为AST节点树。我猜想一旦类已经被编译成字节code AST的所有信息将被丢弃。

P.S. I have spent some time trying to solve the problem by parsing the class in AST level which would be very easy. But I can't find a way to convert already parsed objects to an AST node tree. I guess all AST info is discarded once a class has been compiled into bytecode.

最好的问候雅各布

推荐答案

下面是艰辛的道路。这里是最简单的方式。不知道为什么没有早点发生在我身上。

Below is the hard way. Here's the easy way. Don't know why it didn't occur to me sooner.

import inspect

def get_user_attributes(cls):
    boring = dir(type('dummy', (object,), {}))
    return [item
            for item in inspect.getmembers(cls)
            if item[0] not in boring]


下面是一个开始。


Here's a start

def get_user_attributes(cls):
    boring = dir(type('dummy', (object,), {}))
    attrs = {}
    bases = reversed(inspect.getmro(cls))   
    for base in bases:
        if hasattr(base, '__dict__'):
            attrs.update(base.__dict__)
        elif hasattr(base, '__slots__'):
            if hasattr(base, base.__slots__[0]): 
                # We're dealing with a non-string sequence or one char string
                for item in base.__slots__:
                    attrs[item] = getattr(base, item)
            else: 
                # We're dealing with a single identifier as a string
                attrs[base.__slots__] = getattr(base, base.__slots__)
    for key in boring:
        del attrs['key']  # we can be sure it will be present so no need to guard this
    return attrs

这应该是相当强劲。从本质上讲,它的工作原理是让那些对对象的默认子类的属性忽视。然后,它获取的传递给它,并遍历它相反的顺序,这样子键可以覆盖超键之类的MRO。它返回键 - 值对的字典。如果你想键,值元组就像在一个列表 inspect.getmembers 然后就返回要么 attrs.items()列表(attrs.items())在Python 3。

This should be fairly robust. Essentially, it works by getting the attributes that are on a default subclass of object to ignore. It then gets the mro of the class that's passed to it and traverses it in reverse order so that subclass keys can overwrite superclass keys. It returns a dictionary of key-value pairs. If you want a list of key, value tuples like in inspect.getmembers then just return either attrs.items() or list(attrs.items()) in Python 3.

如果你不真的想穿越MRO,只是想直接在子类中定义的属性然后它更容易:

If you don't actually want to traverse the mro and just want attributes defined directly on the subclass then it's easier:

def get_user_attributes(cls):
    boring = dir(type('dummy', (object,), {}))
    if hasattr(cls, '__dict__'):
        attrs = cls.__dict__.copy()
    elif hasattr(cls, '__slots__'):
        if hasattr(base, base.__slots__[0]): 
            # We're dealing with a non-string sequence or one char string
            for item in base.__slots__:
                attrs[item] = getattr(base, item)
            else: 
                # We're dealing with a single identifier as a string
                attrs[base.__slots__] = getattr(base, base.__slots__)
    for key in boring:
        del attrs['key']  # we can be sure it will be present so no need to guard this
    return attrs

这篇关于检查蟒蛇类属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆