带有和没有显式基类的类之间__dict__的差异

时间:2016-10-04 22:21:53

标签: python python-3.x

为什么(隐式)派生自object的类在其__dict__属性中具有的项比具有显式基类的类多? (python 3.5)。

class X:
    pass
class Y(X):
    pass
X.__dict__
'''
mappingproxy({'__dict__': <attribute '__dict__' of 'X' objects>,
              '__doc__': None,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'X' objects>})
'''

Y.__dict__
'''
mappingproxy({'__doc__': None, '__module__': '__main__'})
'''

1 个答案:

答案 0 :(得分:3)

__weakref____dict__的定义是这样的:调用适当的描述符来访问&#34; real&#34; Python级别代码查找时,弱引用列表的位置和类实例的实例字典。基类object是基本类型,并且不会为实例__weakref____dict__保留空间(weakref.ref(object())将失败,setattr(object(), 'foo', 0)也会失败。< / p>

对于用户定义的类,它需要定义可以找到这些值的描述符(在CPython中,这些访问器通常被绕过,因为在C层有直接指针,但如果你明确引用instance.__dict__,它需要知道如何通过实例的类找到它。 object的第一个孩子(没有__slots__)需要定义这些描述符,因此可以找到它们。子类不需要,因为__dict____weakref__的位置不会改变;他们可以继续使用基类的访问器,因为它们的实例具有相同相对偏移量的那些属性。

基本上,第一个非__slot__用户定义的类正在创建一个实例的概念作为表单的C结构:

struct InstanceObject {
    ... common object stuff ...
    ... anything defined by __slots__ in super class(es), if anything ...
    PyObject *location_of___dict__;
    PyObject *location_of___weakref__;
}

并实现访问器以检查类型以确定那些location*结构成员的偏移量,然后检索它们。子类的struct定义不会更改这些location*成员的偏移量(如果添加了新的__slots__,它们只是附加了),所以它可以从父级重用相同的访问器。