オーバーライドは、クラス __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
プロパティは引き続き使用されます。プロパティが との両方を定義して__dict__
いるため、Python はインスタンスを無視しています。spam
__get__
__set__
a を定義していない記述子を使用すると__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>