要覆盖一个属性,您必须对类而不是实例进行操作,因为它们在实例上的机器在__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
我相信这个技巧可以被视为模板方法设计模式的应用,即使它应用于属性。