我有一个类来缓存一些值,以避免多次计算它们,例如
class A(object):
def __init__(self, a, b):
self.a = a
self.b = b
self._value = None
@property
def value(self):
if self._value is None:
self._value = # <complex code that produces value>
return self._value
通过这种方式,self._value
只计算一次,并且所有其他时间都会返回预先计算的值。到目前为止一切都很好。
现在,假设我想将A
与类B
子类化。在我们的案例中,类B
将有自己的计算方法self._value
但有时需要A
value
,如下例所示:
class B(A):
def __init__(self, a, b):
super().__init__(a, b)
@property
def value(self):
if self._value is not None:
self._value = # <complex code that produces B's version of value>
return self._value
def get_old_value(self):
return super().value # here comes the trouble
现在,显然问题是如果在get_old_value()
之前调用value()
,它将永久缓存A
value
。如果在value()
之前以相同的方式调用get_old_value()
,get_old_value()
实际上将始终返回value()
。
当然,在A
的实现中,可以简单地使用<complex code that produces value>
&#39; get_old_value()
,但这会重复代码(这会使子类化无用)或者甚至将<complex code that produces value>
包装在A
中的另一个方法中,并在get_old_value()
中调用该方法,但这根本不会使用缓存。
另一种方式可能如下:
def get_old_value(self):
result = super().value
self._c = None
return result
但是,无论如何都会删除A
版本的value
的缓存,看起来并不干净。有没有更好的方法来实现这个目标?
我想补充的一点是,在我的代码中A
和B
真正意义上的超类和子类,否则我会考虑组合。
答案 0 :(得分:2)
你需要做的是使用名称修改 - 这将允许每个类/子类维护变量的私有版本,以便它们不会互相破坏:
class A(object):
def __init__(self, a, b):
self.a = a
self.b = b
self.__value = None
@property
def value(self):
if self.__value is None:
self.__value = 7
return self.__value
class B(A):
def __init__(self, a, b):
super().__init__(a, b)
self.__value = None
@property
def value(self):
if self.__value is None:
self.__value = 17
return self.__value
def get_old_value(self):
return super().value # no more trouble here
并在使用中:
>>> b = B(1, 2)
>>> print(b.value)
17
>>> print(b.get_old_value())
7
请注意,您现在也需要在__value
&#39 {s} B
设置__init__
。
另请参阅this answer了解更多关于名称修改的花絮。