覆盖适用于属于类 __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'
正如您所看到的,即使我在实例spam中添加了__dict__条目,它也会被完全忽略,并且仍会使用Foo.spam属性。 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
>>> Foo().desc
Getting Class-stored descriptor, with instance <__main__.foo object at>, class
>>> foo = Foo()
>>> foo.__dict__['desc'] = Descriptor('Instance-stored descriptor')
>>> foo.desc