プロパティをオーバーライドするには、インスタンスではなくクラスに作用する必要があります。これは、インスタンス上のそれらの機構が__dict__
ルックアップの前に呼び出され、最終的にAttributeError
sになるためです。代わりに、クラスに別のプロパティを設定できます。
ただし、これを行うには、インスタンスを作成するたびにクラスを変更するか(これは望ましくないと思います)、新しいクラスを動的に生成する必要があります。
例えば:
class Foo(object):
def __init__(self, val):
self._val = val
@property
def val(self):
return self._val
class SubType(Foo):
def __new__(cls, val):
if val % 2:
#random condition to change the property
subtype = type('SubFoo', (SubType,),
{'val': property((lambda self: self._val + 1))})
return object.__new__(subtype)
else:
return object.__new__(cls)
そして結果は次のとおりです。
>>> d = SubType(3) #property changed
>>> d.val
4
>>> f = SubType(2) #same property as super class
>>> f.val
2
私はこの種のハックはあまり好きではありません。おそらく、物事を行うためのより簡単な方法は、プロパティ値を計算するプライベートメソッドを呼び出すことです。次に例を示します。
class Foo(object):
def __init__(self, val):
self._val = val
def _compute_val(self):
return self._val
@property
def val(self):
return self._compute_val()
class SubFoo(Foo):
def _compute_val(self):
if self._val % 2:
return self._val + 1
else:
return self._val
これにより、以前と同じ結果が得られます。
>>> d = SubFoo(3)
>>> d.val
4
>>> f = SubFoo(2)
>>> f.val
2
このトリックは、プロパティに適用されますが、テンプレートメソッドデザインパターンの適用と見なすことができると思います。