[英]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__
什么?
這最有可能被標記為重復, 但是 ,它很老,主要是關於
Python 2.x
接受的答案是,沒有辦法,但它是在08'提供的。 12'中最新的答案表明dir()
適用於新款式。
相似的標題,不同的內容。
提供
dir()
並inspect
解決方案。
再次提出
dir()
。
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'>,)
因此,由於A
是type
的實例,因此這些方法不是其自己的字典的一部分,而是其類型的字典。
>> 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'})
因為, type
是object
的子類,對type
的dir()
調用將包含來自object
一些項:
>>> set(dir(type)) - set(type.__dict__)
set(['__reduce_ex__', '__str__', '__format__', '__reduce__', '__class__', '__subclasshook__', '__sizeof__'])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.