class C(object):
def f(self):
print self.__dict__
print dir(self)
c = C()
c.f()
输出:
{}
['__class__', '__delattr__','f',....]
为什么self.__dict__中没有'f'
class C(object):
def f(self):
print self.__dict__
print dir(self)
c = C()
c.f()
输出:
{}
['__class__', '__delattr__','f',....]
为什么self.__dict__中没有'f'
dir()
不仅仅是抬头看__dict__
首先,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
s 没有__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']
dir()
实例有什么作用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'
因为该属性已添加到类中__dict__
:
>>> Foo.__dict__['ham']
'eggs'
>>> f.__dict__
{}
请注意实例__dict__
是如何留空的。Python 对象的属性查找遵循对象的层次结构,从实例到类型再到父类以搜索属性。
只有当您直接在实例上设置属性时,您才会看到属性反映在__dict__
实例中,而类__dict__
保持不变:
>>> f.stack = 'overflow'
>>> f.__dict__
{'stack': 'overflow'}
>>> 'stack' in Foo.__dict__
False
dir()
不只是查找对象的__dict__
(有时甚至不存在),它会使用对象的遗产(它的类或类型,以及该类或类型的任何超类或父类)为您提供一个完整的图片所有可用的属性。
实例__dict__
只是该实例上的“本地”属性集,并不包含实例上可用的所有属性。相反,您还需要查看类和类的继承树。
该函数f
属于 class 的字典C
。 c.__dict__
产生特定于实例的属性c
。
>>> class C(object):
def f(self):
print self.__dict__
>>> c = C()
>>> c.__dict__
{}
>>> c.a = 1
>>> c.__dict__
{'a': 1}
C.__dict__
将产生类的属性C
,包括函数f
。
>>> C.__dict__
dict_proxy({'__dict__': <attribute '__dict__' of 'C' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None, 'f': <function f at 0x0313C1F0>})
虽然对象可以引用其类的属性(实际上是所有祖先类),但如此引用的类属性不会成为关联字典本身的一部分。因此,虽然它是对asf
类中定义的函数的合法访问,但它不会作为 in 的属性出现。C
c.f()
c
c.__dict__
>>> c.a = 1
>>> c.__dict__
{'a': 1}
类 dir() 和dict只显示定义的函数(方法)。实例 dir() 显示数据+方法,而其dict仅显示数据属性,而不显示方法。
class C2:
... def __init__(self, id):
... self.id = id
... def set(self, len):
... self.len = len
...
c2 = C2("stick")
dir(C2)
['__class__',.., '__init__', 'set']
dir(c2)
['__class__',.., '__init__', 'id', 'set']
C2.__dict__
mappingproxy({'__init__': <function C2.__init__ at 0x000001899C61E9D0>, 'set': <function C2.set at 0x000001899C61ED30>,...})
c2.__dict__
{'id': 'stick'}