Python中的属性访问:先槽位,再__dict__?
在下面的例子中,虽然属性 x
在 __dict__
中存在,但还是从对象的槽位中访问了 x
(这并不是一个典型或者特别有用的情况,不过我很好奇):
>>> class C(object):
... __slots__ = 'x'
...
>>> class D(C):
... pass
...
>>> obj = D()
>>> obj.x = 'Stored in slots'
>>> obj.__dict__
{}
>>> obj.__dict__['x'] = 'stored in __dict__'
>>> obj.x
'Stored in slots'
这种访问顺序(先看槽位)是有文档说明的吗?还是说只是实现上的细节?
1 个回答
11
是的,一个对象的 __dict__
只有在查找完数据描述符之后才会被查看。__slots__
属性就是作为数据描述符来实现的。
可以参考 调用描述符 的内容:
在实例绑定中,描述符的调用优先级取决于定义了哪些描述符方法。描述符可以定义
__get__()
、__set__()
和__delete__()
的任意组合。如果它没有定义__get__()
,那么访问这个属性时会返回描述符对象本身,除非对象的实例字典里有值。如果描述符定义了__set__()
和/或__delete__()
,那么它就是一个数据描述符;如果都没有定义,它就是一个非数据描述符。通常,数据描述符会同时定义__get__()
和__set__()
,而非数据描述符只会有__get__()
方法。定义了__set__()
和__get__()
的数据描述符总是会覆盖实例字典中的重定义。相反,非数据描述符可以被实例覆盖。
同样在那一页,还有关于 slots 的部分:
__slots__
是在类级别实现的,为每个变量名创建描述符(实现描述符)。因此,类属性不能用来为由__slots__
定义的实例变量设置默认值;否则,类属性会覆盖描述符的赋值。