首先与A.__dict__.__dict__
有所不同A.__dict__['__dict__']
,前者不存在。后者是__dict__
类实例所具有的属性。这是一个描述符对象,它返回特定实例的内部属性字典。简而言之,__dict__
对象的属性不能存储在对象的中__dict__
,因此可以通过类中定义的描述符进行访问。
简短版本:
长版:
类和对象都通过属性运算符(通过类或元类的实现__getattribute__
)以及由使用的__dict__
属性/协议来提供对属性的访问vars(ob)
。
对于普通对象,该__dict__
对象创建一个单独的dict
对象,该对象存储属性,然后__getattribute__
首先尝试访问该对象并从那里获取属性(在尝试通过使用描述符协议在类中查找属性之前,以及在调用之前__getattr__
)。在__dict__
对类描述符实现了上网本字典。
由于不可能将__dict__
ofinstance
存储在__dict__
实例中,因此可以直接通过描述符协议进行访问,并将其存储在实例的特殊字段中。
对于类,__dict__
也存在类似的情况,尽管它们是一个特殊的代理对象,它伪装成字典(但可能不是内部的),并且不允许您更改它或将其替换为另一个。除其他所有功能外,该代理还允许您访问特定于该类且未在其基础之一中定义的类的属性。
默认情况下,vars(cls)
空类的a带有三个描述符-__dict__
用于存储实例的属性(该类在__weakref__
内部由)使用weakref
,以及该类的文档字符串。如果定义,则前两个可能会消失__slots__
。然后,您将没有__dict__
and__weakref__
属性,但是每个插槽只有一个class属性。这样,实例的属性就不会存储在字典中,而对它们的访问将由类中的相应描述符提供。
最后,与之A.__dict__
不同的A.__dict__['__dict__']
是,因为该属性从未__dict__
例外地在中查找过,所以对它的正确性对于实际上将要使用的任何其他属性都不是正确的。例如,与是同一件事。如果不存在这种不一致,则使用将不起作用,而您必须始终使用它。 __vars(A)``A.__weakref__``A.__dict__['__weakref__']``A.__dict__``vars(A)