首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Python类的__dict__.__dict__属性是什么?

Python类的__dict__.__dict__属性是什么?
EN

Stack Overflow用户
提问于 2011-02-03 00:52:57
回答 3查看 87.3K关注 0票数 101
>>> 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?

如果我执行A.something = 10,这将进入A.__dict__。What is this <attribute '__dict__' of 'A' objects> A.__dict__.__dict__ in A.__dict__.__dict__?它什么时候包含某些东西?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-02-03 01:26:03

首先,A.__dict__.__dict__不同于A.__dict__['__dict__']。前者不存在,后者是类的实例将具有的__dict__属性。它是一个数据描述符对象,返回特定实例的内部属性字典。简而言之,对象的__dict__属性不能存储在对象的__dict__中,因此可以通过类中定义的描述符来访问它。

要理解这一点,您必须阅读documentation of the descriptor protocol

简短的版本如下:

  1. 对于类a的实例A,对a.__dict__的访问由与vars(A)['__dict__'].
  2. For a类A相同的A.__dict__['__dict__']提供,对A.__dict__的访问(理论上)由与vars(type)['__dict__'].

相同的type.__dict__['__dict__']提供

长版本:

类和对象都通过属性操作符(通过类或元类的__getattribute__实现)和vars(ob)使用的__dict__属性/协议提供对属性的访问。

对于普通对象,__dict__对象创建一个单独的dict对象,该对象存储属性,__getattribute__首先尝试访问该对象并从中获取属性(在尝试利用描述符协议在类中查找属性之前,以及在调用__getattr__之前)。类上的__dict__描述符实现了对此字典的访问。

  • a.name等同于按顺序尝试:type(a).__dict__['name'].
  • a.__dict__ (仅当type(a).__dict__['name']是数据描述符时)、type(a).__dict__['name'].__get__(a, type(a))type(a).__dict__['name'].__get__(a, type(a))type(a).__dict__['name'].__get__(a, type(a))执行相同的操作,但由于显而易见的原因跳过了第二步。

由于实例的描述符不可能存储在自身中,因此需要通过__dict__协议直接访问,并将其存储在实例中的一个特殊字段中。

类似的情况也适用于类,尽管它们的__dict__是一个特殊的代理对象,它伪装成一个字典(但可能不在内部),并且不允许您更改它或用另一个字典替换它。此代理允许您访问特定于它的类的属性,而不是在它的某个基类中定义的属性。

默认情况下,空类的vars(cls)包含三个描述符:用于存储实例属性的__dict__、供weakref内部使用的__weakref__和类的文档字符串__doc__。如果您定义__slots__,前两个可能会消失。那么您就不会有__dict____weakref__属性,而是每个插槽都有一个单独的class属性。这样,实例的属性就不会存储在字典中,对它们的访问将由类中相应的描述符提供。

最后,A.__dict__不同于A.__dict__['__dict__']的不一致之处在于,属性__dict__vars(A)中是例外的,所以它适用的条件实际上并不适用于您要使用的任何其他属性。例如,A.__weakref__A.__dict__['__weakref__']是一样的。如果不存在这种不一致,使用A.__dict__将不起作用,您必须始终使用vars(A)

票数 112
EN

Stack Overflow用户

发布于 2016-06-07 07:52:28

您可以尝试下面的简单示例来了解更多内容:

>>> 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

从上面的例子可以看出,实例属性由它们的类存储,而类属性由它们的元类存储。这也可以通过以下方式进行验证:

>>> a.__dict__ == A.__getattribute__(a, '__dict__')
True
>>> A.__dict__ == type.__getattribute__(A, '__dict__')
True
票数 11
EN

Stack Overflow用户

发布于 2011-02-03 01:38:05

让我们来探索一下吧!

>>> A.__dict__['__dict__']
<attribute '__dict__' of 'A' objects>

我想知道那是什么?

>>> type(A.__dict__['__dict__'])
<type 'getset_descriptor'>

getset_descriptor对象有哪些属性?

>>> type(A.__dict__["__dict__"]).__dict__
<dictproxy object at 0xb7efc4ac>

通过复制该dictproxy,我们可以找到一些有趣的属性,特别是__objclass____name__

>>> A.__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__
(<class '__main__.A'>, '__dict__')

所以__objclass__是对A的引用,而__name__只是字符串'__dict__',也许是属性的名称?

>>> getattr(A.__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__) == A.__dict__
True

这就对了!A.__dict__['__dict__']是一个可以反向引用A.__dict__的对象。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4877290

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档