为什么(隐式)派生自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__'})
'''
答案 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__
,它们只是附加了),所以它可以从父级重用相同的访问器。