您已经成功创建了正确的非数据描述符,但是随后通过设置实例属性来 屏蔽 该
d属性。
因为它是一个 非
数据描述符,所以实例属性在这种情况下会获胜。添加
__set__方法时,将描述符变成数据描述符,并且即使存在实例属性,也始终应用数据描述符。(*)
从 描述符方法 :
属性访问的默认行为是从对象的字典中获取,设置或删除属性。例如,
a.x有一个查找链,从a.__dict__['x'],然后到type(a).__dict__['x'],并一直到type(a)排除元类的基类。如果查找到的值是定义描述符方法之一的对象,则Python可能会覆盖默认行为并改为调用描述符方法。优先级链在何处发生取决于定义了哪些描述符方法。
和
如果对象同时定义
__get__()和__set__(),则将其视为数据描述符。仅定义__get__()的描述符称为非数据描述符(它们通常用于方法,但也可以用于其他用途)。数据和非数据描述符的不同之处在于,如何计算实例字典中条目的替代值。如果实例的字典具有与数据描述符同名的条目,则数据描述符优先。如果实例的字典具有与非数据描述符同名的条目,则该字典条目优先。
如果您 删除 的
d实例属性(从来没有对它进行设置或从实例中删除),描述对象被调用:
>>> class D(object):... def __init__(self, x = 1395):... self.x = x... def __get__(self, instance, owner):... print "getting", self.x... return self.x...>>> class C(object):... d = D()...>>> c = C()>>> c.dgetting 13951395
再次添加一个实例属性,由于实例属性获胜,描述符将被忽略:
>>> c.d = 42 # setting an instance attribute>>> c.d42>>> del c.d # deleting it again>>> c.dgetting 13951395
另请参见Python数据 模型 参考中的 调用描述符
文档。
__
(*)如果数据描述符实现了
__get__挂钩。 除非 存在于中, 否则
通过访问此类描述符
instance.attribute_name将返回描述符对象。
'attribute_name'``instance.__dict__



