覆盖适用于属于类 __dict__
的描述符。
Python 将始终查找type(instance).__dict__[attributename].__get__(instance, type(instance))
,并且不会用于instance.__dict__
搜索实例覆盖。
这是一个使用人为Descriptor
类和属性的示例(这是一个带有 a__get__
和 a的描述符__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'
如您所见,即使我spam
在实例中添加了一个条目__dict__
,它也被完全忽略,并且Foo.spam
仍然使用该属性。Python 忽略了该实例__dict__
,因为该spam
属性同时定义了__get__
和 a __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>