首先,dir()
是一种API方法,它知道如何使用属性__dict__
来查找对象的属性。
但是,并非所有对象都具有__dict__
属性。例如,如果要向自定义类添加__slots__
属性,则该类的实例将没有__dict__
属性,但dir()
仍可以列出这些实例上的可用属性:
>>> class Foo(object):
... __slots__ = ('bar',)
... bar = 'spam'
...
>>> Foo().__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__dict__'
>>> dir(Foo())
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'bar']
同样适用于许多内置类型。list
没有__dict__
属性,但是您仍然可以使用列出所有属性dir()
:
>>> [].__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute '__dict__'
>>> dir([])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
Python实例具有自己的__dict__
,但它们的类也有:
>>> class Foo(object):
... bar = 'spam'
...
>>> Foo().__dict__
{}
>>> Foo.__dict__.items()
[('__dict__', <attribute '__dict__' of 'Foo' objects>), ('__weakref__', <attribute '__weakref__' of 'Foo' objects>), ('__module__', '__main__'), ('bar', 'spam'), ('__doc__', None)]
该dir()
方法使用 两种 这些__dict__
属性, 并且 一来就object
上创建实例,类可用属性的完整列表,并在类的所有祖先。
>>> f = Foo()
>>> f.ham
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'ham'
>>> Foo.ham = 'eggs'
>>> f.ham
'eggs'
>>> Foo.__dict__['ham']
'eggs'
>>> f.__dict__
{}
注意实例如何__dict__
留空。在Python对象上进行属性查找遵循对象的层次结构,从实例到类型,再到父类,以搜索属性。
仅当直接在实例上设置属性时,您才可以在实例保持不变__dict__
的情况下看到反映在实例中的属性__dict__
:
>>> f.stack = 'overflow'
>>> f.__dict__
{'stack': 'overflow'}
>>> 'stack' in Foo.__dict__
False
dir()
不仅查找对象__dict__
(有时甚至不存在),它还将使用对象的遗产(其类或类型,以及该类或类型的任何超类或父级)为您提供完整的图像所有可用的属性。