Data descriptors with
__set__()
and__get__()
defined always override a redefinition in an instance dictionary.
我对这句话的理解没问题,但是有人能帮我解释一下为什么会有这样的规则吗?毕竟,如果我想覆盖实例字典中的属性,我已经需要明确地(inst.__dict__["attr"] = val
),因为天真的 inst.attr = val
会调用描述符的 __set__
方法,这(通常)不会覆盖实例字典中的属性。
编辑:澄清一下,我明白发生了什么,我的问题是为什么要制定这样的规则。
最佳答案
覆盖适用于属于类 __dict__
的描述符。
Python 将始终查找 type(instance).__dict__[attributename].__get__(instance, type(instance))
,不会使用 instance .__dict__
搜索实例覆盖。
这是一个使用人为设计的 Descriptor
类和属性(这是一个带有 __get__
和 __set__
的描述符的示例:
>>> class Descriptor(object):
... def __init__(self, name):
... self.name = name
... def __get__(self, instance, cls):
... print 'Getting %s, with instance %r, class %r' % (self.name, instance, cls)
...
>>> class Foo(object):
... _spam = 'eggs'
... @property
... def spam(self):
... return self._spam
... @spam.setter
... def spam(self, val):
... self._spam = val
...
>>> Foo().spam
'eggs'
>>> foo = Foo()
>>> foo.__dict__['spam'] = Descriptor('Override')
>>> foo.spam
'eggs'
如您所见,即使我在实例 __dict__
中添加了一个 spam
条目,它也被完全忽略并且 Foo.spam
属性(property)仍在使用。 Python 忽略实例 __dict__
因为 spam
属性同时定义了 __get__
和 __set__
。
如果您使用的描述符没有定义__set__
,则覆盖有效(但它的__get__
未被调用:
>>> class Foo(object):
... desc = Descriptor('Class-stored descriptor')
...
>>> Foo.desc
Getting Class-stored descriptor, with instance None, class <class '__main__.Foo'>
>>> Foo().desc
Getting Class-stored descriptor, with instance <__main__.Foo object at 0x1018df510>, class <class '__main__.Foo'>
>>> foo = Foo()
>>> foo.__dict__['desc'] = Descriptor('Instance-stored descriptor')
>>> foo.desc
<__main__.Descriptor object at 0x1018df1d0>
关于python数据和非数据描述符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13007179/