__dict__ Python 中 Class、object 的终极基础属性

__dict__ Attribute of Ultimate Base Class, object in Python

以下代码按排序顺序列出了名为 'A' 的 class 的属性:-

>>> class A():
        def __init__(self, i):
            self.at = i

>>> sorted(vars(A))
['__dict__', '__doc__', '__init__', '__module__', '__weakref__']

现在,打印键的值,'__dict__' 结果如下:-

>>> vars(A)['__dict__']                 #Value of '__dict__'
<attribute '__dict__' of 'A' objects>

根据文档,vars([object])

Return the __dict__ attribute for a module, class, instance, or any other object with a __dict__ attribute.


我不明白的是列表中的 '__dict__' 属性与 vars() 到 return 使用的 相同的属性 A 的属性,或者它是一个 不同的属性 ,它有一些其他 objective 像 实现 A 的 objects' 命名空间 按照建议 (根据我的说法)'__dict__' 持有的值。


编辑:-

问题的第一部分与此 other question 非常相关(也由 @eliotness 提到),但它是第二部分(如下所述),我找不到任何答案或相关问题,因此,更改问题的标题。


让我们考虑另一个代码,它在 Python、object:-

中生成最终基 class 的属性列表
>>> sorted(vars(object))
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', ...., '__str__', '__subclasshook__']
>>> hasattr(object, '__dict__')
True
>>> sorted(getattr(object, '__dict__')) == sorted(vars(object))
True

文档中关于 object.__dict__

的另一段引述

A dictionary or other mapping object used to store an object’s (writable) attributes.


这一次,'__dict__' 没有出现在 object 的列表中。那么,在 object 或任何其他原因的情况下, __dict__ 属性是否是 read-only 属性?

此外,是否可以通过任何方式在 Python 中获得 read-only 属性 的列表?


首先我想说我只是部分知道你问题的答案。关于 python 的行为,第二部分可能并不完全正确。但首先,我想澄清一些事情:你引用的文档是关于普通对象的,可能不适用于 meta-classes,因为它们的内部行为完全用 C 编码。

vars(A)['dict']

据我了解 python 的工作原理,我怀疑您在这里看到的 __dict__

>>> vars(A)['__dict__']                 #Value of '__dict__'
<attribute '__dict__' of 'A' objects>

我怀疑它是 class 未来实例的 __dict__ 属性的样本。我现在没有更好的答案,但让我们继续挖掘。

meta-classes

上的 __dict__ 属性

因为 object 是 class 的一个 type 很正常,因为它没有 __dict__ 因为不可能在基本类型上添加属性像 int、float 或 str。那么,如果不使用这些类型,为什么会有 __dict__ 属性呢?

最后,是的。 classes 和 meta-classes 的 __dict__ 属性有限制。这些限制采取 class MappingProxy 的形式,如 vars documentation:

中所述

Objects such as modules and instances have an updateable __dict__ attribute; however, other objects may have write restrictions on their __dict__ attributes (for example, classes use a types.MappingProxyType to prevent direct dictionary updates).

但是这种行为在doc of the class object

中也有明确说明

编辑:我开始寻找关于怪人 vars(A)['__dict__'] 的有用信息。看看here

class 上的 linked answer: the __dict__ of instances is stored as a descriptor 已经回答了您问题的第一部分。这就是A.__dict__['__dict__']。另一方面,A.__dict__ 存储 A class 的所有属性 - 它本身是 type 的一个实例。所以实际上是 type.__dict__['__dict__'] 提供了这些变量:

>>> type.__dict__['__dict__']
<attribute '__dict__' of 'type' objects>
>>> A.__dict__ == type.__dict__['__dict__'].__get__(A)
True

您在 object 上看不到 __dict__ 属性的原因是它没有。这意味着您不能在 object 个实例上设置实例变量:

>>> o = object()
>>> o.x = 1

AttributeError: 'object' object has no attribute 'x'

自定义 classes 可以通过定义 __slots__:

实现类似的行为
>>> class B:
...     __slots__ = ()
... 
>>> vars(B)
mappingproxy({'__module__': '__main__', '__slots__': (), '__doc__': None})
>>> 
>>> b = B()
>>> b.x = 1

AttributeError: 'B' object has no attribute 'x'