簡體   English   中英

獲取所有可能的類屬性的完整列表

[英]Get complete list of all possible Class Attributes

有一種方法,給定一個簡單的類,輸出所有可能的屬性嗎? 標准屬性,如__class____doc__ 以及 特殊的只讀屬性,__mro____bases__等。 一般來說, 所有現有屬性?

考慮一個類最簡單的情況:

class myClass:
    pass

dir()vars()inspect.getmembers()都排除了某些builtin屬性。 最完整的列表是使用myClass.__dir__(MyClass)提供的,在添加內置屬性時,它排除了MyClass用戶定義屬性,例如:

In [3]: set(MyClass.__dir__(MyClass)) - set(dir(MyClass))
Out[3]: 
{'__abstractmethods__', '__base__', '__bases__',
 '__basicsize__', '__call__', '__dictoffset__',
 '__flags__', '__instancecheck__', '__itemsize__',
 '__mro__', '__name__', '__prepare__', '__qualname__',
 '__subclasscheck__', '__subclasses__', '__text_signature__',
 '__weakrefoffset__', 'mro'}

根據其中一個類似的問題,這是不可能的。 如果目前仍然不可能,那么“隱藏” 某些屬性(如__bases__ (從標准調用到dir(), vars() & inspect而不是像__name__這樣的__name__什么?


類似問題:

dir()基本上是一個方便的方法,它不應該返回所有內容,它基本上做的是它遞歸地返回在類的字典及其基礎中找到的所有內容。

PyPy的dir()實現很容易理解:

def dir(*args):
    ...
    elif isinstance(obj, (types.TypeType, types.ClassType)):
        # Don't look at __class__, as metaclass methods would be confusing.
        return sorted(_classdir(obj))
    ...

def _classdir(klass):
    """Return a set of the accessible attributes of class/type klass.

    This includes all attributes of klass and all of the base classes
    recursively.
    """
    names = set()
    ns = getattr(klass, '__dict__', None)
    if ns is not None:
        names.update(ns)
    bases = getattr(klass, '__bases__', None)
    if bases is not None:
        # Note that since we are only interested in the keys, the order
        # we merge classes is unimportant
        for base in bases:
            names.update(_classdir(base))
    return names

由於每個類基本上都是從object繼承的,因此它們會包含一些dunder方法,因為它們實際上是object字典的一部分:

>>> class A(object):
    pass
...
>>> set(dir(A)) == set(list(object.__dict__) + list(A.__dict__))
True

那么__bases__和其他缺少的項目呢?

首先, object本身就是某個東西的實例, 實際上它有點混亂

>>> isinstance(type, object)
True
>>> isinstance(object, type)
True
>>> issubclass(type, object)
True
>>> issubclass(object, type)
False
>>> type.mro(object)
[<type 'object'>]
>>> type.mro(type)
[<type 'type'>, <type 'object'>]

所以, __bases____ge__等所有屬性實際上都是type一部分:

>>> list(type.__dict__)
['__module__', '__abstractmethods__', '__getattribute__', '__weakrefoffset__', '__dict__', '__lt__', '__init__', '__setattr__', '__subclasses__', '__new__', '__base__', '__mro__', 'mro', '__dictoffset__', '__call__', '__itemsize__', '__ne__', '__instancecheck__', '__subclasscheck__', '__gt__', '__name__', '__eq__', '__basicsize__', '__bases__', '__flags__', '__doc__', '__delattr__', '__le__', '__repr__', '__hash__', '__ge__']

因此,當我們做A.__bases__我們實際上是A type 查找描述符 ,即type

>>> A.__bases__
(<type 'object'>,)
>>> type(A).__dict__['__bases__'].__get__(A, type)
(<type 'object'>,)

因此,由於Atype的實例,因此這些方法不是其自己的字典的一部分,而是其類型的字典。

>> class A(object):
...     spam = 'eggs'
...
>>> a = A()
>>> a.foo = 100
>>> a.bar = 200
>>> a.__dict__
{'foo': 100, 'bar': 200}
>>> A.__dict__
dict_proxy({'__dict__': <attribute '__dict__' of 'A' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None, 'spam': 'eggs'})

因為, typeobject的子類,對typedir()調用將包含來自object一些項:

>>> set(dir(type)) - set(type.__dict__)
set(['__reduce_ex__', '__str__', '__format__', '__reduce__', '__class__', '__subclasshook__', '__sizeof__'])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM