获取所有可能的类属性的完整列表 [英] Get complete list of all possible Class Attributes
问题描述
给定一个简单的Class,是否有一种方法可以输出所有可能的属性? __class__
和__doc__
和 等标准属性特殊只读属性,例如__mro__
,__bases__
等.通常, 所有 是否显示属性?
Is there a way, given a simple Class, to output all the possible attributes for it? Standard attributes like __class__
and __doc__
and special read only attributes like __mro__
, __bases__
et al. Generally, all present attributes?
考虑类的最简单情况:
class myClass:
pass
dir()
,vars()
和inspect.getmembers()
均排除某些builtin
属性.使用myClass.__dir__(MyClass)
可以提供最完整的列表,该列表在添加内置属性时会排除用户定义的MyClass
属性,例如:
The dir()
, vars()
and inspect.getmembers()
all exclude certain builtin
attributes. The most complete list is offered by using myClass.__dir__(MyClass)
which, while adding built in attributes, excludes user defined attributes of MyClass
, for example:
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__
的那些))背后的原理是什么?
According to one of the added similar questions, this is not possible. If presently still not possible, what is the rationale behind "hiding" certain attributes like __bases__
(from standard calls to dir(), vars() & inspect
and not ones like __name__
?
这是最有可能被标记为重复的内容, 但是 ,它很旧,并且大多与
Python 2.x
有关.可以接受的答案是,没有办法,但是它是在08'中提供的. 12'中的最新答案建议dir()
用于新样式类.
This is the most likely to be labeled as a duplicate, but, it is old and mostly regarding
Python 2.x
. The accepted answer is that there isn't a way but it was provided in 08'. The most recent answer in 12' suggestsdir()
for new style classes.
相似的标题,不同的内容.
Similar title, different content.
提供
dir()
和inspect
解决方案.
同样,提出
dir()
.
推荐答案
dir()
基本上是一种方便的方法,它不应该返回所有内容,它的主要作用是递归地返回在类及其基数的字典中找到的所有内容.
dir()
is basically a convenience method, it is not supposed to return everything, what it basically does is that it recursively returns everything found in the dictionary of a class and its bases.
PyPy's implementation of dir()
is quite easy to understand:
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
词典的一部分:
As each class basically inherits from object
you will see some dunder methods included because they are actually part of object
's dictionary:
>>> class A(object):
pass
...
>>> set(dir(A)) == set(list(object.__dict__) + list(A.__dict__))
True
现在
__bases__
和其他遗失物品怎么办?
Now what about
__bases__
and other missing items?
首先object
本身是某物的一个实例,嗯,实际上有点混乱:>
First of all object
itself is an instance of something, well it's bit of a mess actually:
>>> 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
的一部分:
So, all of the attributes like __bases__
, __ge__
etc are actually part of 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__']
Hence when we do A.__bases__
we are actually looking up a descriptor on type of A
, i.e type
:
>>> A.__bases__
(<type 'object'>,)
>>> type(A).__dict__['__bases__'].__get__(A, type)
(<type 'object'>,)
因此,由于A
是type
的实例,所以这些方法不是其自身词典的一部分,而是其类型的词典的一部分.
So, as A
is an instance of type
these methods are not part of its own dictionary but its type's dictionary.
>> 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
中的某些项目:
As, type
is a subclass of object
, the dir()
call on type
will contain some items from object
:
>>> set(dir(type)) - set(type.__dict__)
set(['__reduce_ex__', '__str__', '__format__', '__reduce__', '__class__', '__subclasshook__', '__sizeof__'])
这篇关于获取所有可能的类属性的完整列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!