Python中的属性访问:先槽位,再__dict__?

7 投票
1 回答
1617 浏览
提问于 2025-04-17 17:27

在下面的例子中,虽然属性 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__ 定义的实例变量设置默认值;否则,类属性会覆盖描述符的赋值。

撰写回答