Python 类的 __dict__.__dict__ 属性是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4877290/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the __dict__.__dict__ attribute of a Python class?
提问by porgarmingduod
>>> class A(object): pass
...
>>> A.__dict__
<dictproxy object at 0x173ef30>
>>> A.__dict__.__dict__
Traceback (most recent call last):
File "<string>", line 1, in <fragment>
AttributeError: 'dictproxy' object has no attribute '__dict__'
>>> A.__dict__.copy()
{'__dict__': <attribute '__dict__' of 'A' objects> ... }
>>> A.__dict__['__dict__']
<attribute '__dict__' of 'A' objects> # What is this object?
If I do A.something = 10, this goes into A.__dict__. What isthis <attribute '__dict__' of 'A' objects>found in A.__dict__.__dict__, and when does it contain something?
如果我这样做A.something = 10,这将进入A.__dict__. 这是在 中<attribute '__dict__' of 'A' objects>找到的A.__dict__.__dict__,何时包含某些内容?
采纳答案by Rosh Oxymoron
First of all A.__dict__.__dict__is different from A.__dict__['__dict__'], and the former doesn't exist. The latter is the __dict__attribute that the instances of the class would have. It's a descriptor object that returns the internal dictionary of attributes for the specific instance. In short, the __dict__attribute of an object can't be stored in object's __dict__, so it's accessed through a descriptor defined in the class.
首先与A.__dict__.__dict__不同A.__dict__['__dict__'],前者不存在。后者是__dict__类的实例将具有的属性。它是一个描述符对象,返回特定实例的内部属性字典。简而言之,__dict__对象的属性无法存储在对象的 中__dict__,因此通过类中定义的描述符来访问它。
To understand this, you'd have to read the documentation of the descriptor protocol.
The short version:
简短版本:
- For an instance of class
A, access toinstance.__dict__is provided byA.__dict__['__dict__']which is the same asvars(A)['__dict__']. - For the class A, access to
A.__dict__is provided bytype.__dict__['__dict__'](in theory) which is the same asvars(type)['__dict__'].
- 对于类的实例
A,访问instance.__dict__由A.__dict__['__dict__']which提供与vars(A)['__dict__']. - 对于 A 类,访问
A.__dict__由type.__dict__['__dict__'](理论上)提供,与vars(type)['__dict__'].
The long version:
长版:
Both classes and objects provide access to attributes both through the attribute operator (implemented via the class or metaclass's __getattribute__), and the __dict__attribute/protocol which is used by vars(ob).
类和对象都通过属性运算符(通过类或元类的 实现__getattribute__)和 使用的__dict__属性/协议提供对属性的访问vars(ob)。
For normal objects, the __dict__object creates a separate dictobject, which stores the attributes, and __getattribute__first tries to access it and get the attributes from there (before attempting to look for the attribute in the class by utilizing the descriptor protocol, and before calling __getattr__). The __dict__descriptor on the class implements the access to this dictionary.
对于普通对象,该__dict__对象创建一个单独的dict对象来存储属性,并__getattribute__首先尝试访问它并从那里获取属性(在尝试使用描述符协议在类中查找属性之前,以及在调用 之前__getattr__)。在__dict__对类描述符实现了上网本字典。
x.nameis equivalent to trying those in order:x.__dict__['name'],type(x).name.__get__(x, type(x)),type(x).namex.__dict__does the same but skips the first one for obvious reasons
x.name相当于按顺序尝试:x.__dict__['name'],type(x).name.__get__(x, type(x)),type(x).namex.__dict__做同样的事情,但出于明显的原因跳过了第一个
As it's impossible for the __dict__of instanceto be stored in __dict__of the instance, it is accessed through the descriptor protocol directly instead, and is stored in a special field in the instance.
由于__dict__of不可能instance存储在__dict__实例中,所以直接通过描述符协议访问,并存储在实例中的一个特殊字段中。
A similar scenario is true for classes, although their __dict__is a special proxy object that pretends to be a dictionary (but might not be internally), and doesn't allow you to change it or replace it with another one. This proxy allows you, among all else, to access the attributes of a class that are specific to it, and not defined in one of its bases.
类也有类似的情况,尽管它们__dict__是一个特殊的代理对象,它伪装成一个字典(但可能不是内部的),并且不允许您更改它或将其替换为另一个。除其他外,此代理允许您访问特定于它的类的属性,而不是在其基类之一中定义。
By default, a vars(cls)of an empty class carries three descriptors - __dict__for storing the attributes of the instances, __weakref__which is used internally by weakref, and the docstring of the class. The first two might be gone if you define __slots__. Then you wouldn't have __dict__and __weakref__attributes, but instead you'd have a single class attribute for each slot. The attributes of the instance then wouldn't be stored in a dictionary, and access to them will be provided by the respective descriptors in the class.
默认情况下,vars(cls)空类的 a 携带三个描述符 -__dict__用于存储实例的属性,由__weakref__内部使用weakref,以及类的文档字符串。如果你定义了前两个可能会消失__slots__。那么你不会有__dict__and__weakref__属性,而是每个插槽都有一个类属性。实例的属性不会存储在字典中,并且对它们的访问将由类中的相应描述符提供。
And lastly, the inconsistency that A.__dict__is different from A.__dict__['__dict__']is because the attribute __dict__is, by exception, neverlooked up in vars(A), so what is true for it isn't true for practically any other attribute you'd use. For example, A.__weakref__is the same thing as A.__dict__['__weakref__']. If this inconsistency didn't exist, using A.__dict__would not work, and you'd have to always use vars(A)instead.
最后,与A.__dict__不同的不一致A.__dict__['__dict__']是因为该属性__dict__在例外情况下从未在 中查找过vars(A),因此对于您使用的几乎任何其他属性来说,它的真实性都不是真实的。例如,A.__weakref__与A.__dict__['__weakref__']. 如果这种不一致不存在,使用A.__dict__将不起作用,您必须始终使用vars(A)。
回答by vz0
Since A.__dict__is a dictionary storing Aattributes, A.__dict__['__dict__']is the direct reference to that same A.__dict__attribute.
因为A.__dict__是存储A属性的字典,所以A.__dict__['__dict__']是对同一A.__dict__属性的直接引用。
A.__dict__contains a (kind-of) reference to itself. The "kind-of" part is why the expression A.__dict__returns a dictproxyinstead of a normal dict.
A.__dict__包含对自身的(某种)引用。“种类”部分是表达式A.__dict__返回 adictproxy而不是普通dict.
>>> class B(object):
... "Documentation of B class"
... pass
...
>>> B.__doc__
'Documentation of B class'
>>> B.__dict__
<dictproxy object at 0x00B83590>
>>> B.__dict__['__doc__']
'Documentation of B class'
回答by Andrew Clark
Lets do some exploring!
让我们做一些探索!
>>> A.__dict__['__dict__']
<attribute '__dict__' of 'A' objects>
I wonder what that is?
我想知道那是什么?
>>> type(A.__dict__['__dict__'])
<type 'getset_descriptor'>
What attributes does a getset_descriptorobject have?
getset_descriptor对象有哪些属性?
>>> type(A.__dict__["__dict__"]).__dict__
<dictproxy object at 0xb7efc4ac>
By making a copy of that dictproxywe can find some interesting attributes, specifically __objclass__and __name__.
通过复制它,dictproxy我们可以找到一些有趣的属性,特别是__objclass__和__name__。
>>> A.__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__
(<class '__main__.A'>, '__dict__')
So __objclass__is a reference to Aand __name__is just the string '__dict__', name of an attribute perhaps?
那么__objclass__是对A并且__name__只是字符串'__dict__',属性名称的引用吗?
>>> getattr(A.__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__) == A.__dict__
True
There we have it! A.__dict__['__dict__']is an object that can refer back to A.__dict__.
我们有! A.__dict__['__dict__']是一个可以引用回的对象A.__dict__。
回答by damaZhang
You can try the following simple example to understand more of this:
您可以尝试以下简单示例来了解更多信息:
>>> class A(object): pass
...
>>> a = A()
>>> type(A)
<type 'type'>
>>> type(a)
<class '__main__.A'>
>>> type(a.__dict__)
<type 'dict'>
>>> type(A.__dict__)
<type 'dictproxy'>
>>> type(type.__dict__)
<type 'dictproxy'>
>>> type(A.__dict__['__dict__'])
<type 'getset_descriptor'>
>>> type(type.__dict__['__dict__'])
<type 'getset_descriptor'>
>>> a.__dict__ == A.__dict__['__dict__'].__get__(a)
True
>>> A.__dict__ == type.__dict__['__dict__'].__get__(A)
True
>>> a.__dict__ == type.__dict__['__dict__'].__get__(A)['__dict__'].__get__(a)
True
From the above example, it seems that class objects attributes are stored by their class, class's attributes are stored by their class, which are metaclasses. This is also validated by:
从上面的例子来看,似乎类对象的属性是由它们的类存储的,类的属性是由它们的类存储的,它们是元类。这也得到了验证:
>>> a.__dict__ == A.__getattribute__(a, '__dict__')
True
>>> A.__dict__ == type.__getattribute__(A, '__dict__')
True

