2017-03-20 46 views
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 = # <complex code that produces value> 
     return self._value 

这样,self._value只计算一次,所有的其他时间返回预先计算的值。到现在为止还挺好。

现在,我们假设我想要A的子类B。在我们的例子类B都会有自己的计算self._value的方法,但它有时需要Avalue,就像这个例子:

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()之前调用它会缓存Avalue永远。如果value()以相同的方式在get_old_value()之前被调用,get_old_value()实际上总是会返回value()

当然,人们可以简单地使用A<complex code that produces value>,在get_old_value()执行,而且会重复的代码(这几乎使继承没用),甚至在A包裹<complex code that produces value>内的另一种方法,并调用该方法get_old_value()但是这根本不会使用缓存。

另一种方式可能是以下几点:

def get_old_value(self): 
    result = super().value 
    self._c = None 
    return result 

但无论如何都会删除缓存A的版本value,不看干净的。有没有更好的方法来完成这个?

我想补充的一件事是,在我的代码AB作为超类和子类非常有意义,否则我会考虑组合。

回答

2

你需要做的是使用名称忙玲 - 这将允许每个类/子类来保持变量的私人版本,所以他们不揍对方:

​​

而且在使用:

>>> b = B(1, 2) 
>>> print(b.value) 
17 
>>> print(b.get_old_value()) 
7 

请注意,您现在需要设置B__init____value为好。

另请参阅this answer了解更多有关名称修饰的小技巧。

+0

感谢您的回答!如果你有兴趣,你可以在这里找到后续问题:http://stackoverflow.com/questions/42917216/followup-attribute-caching-in-superclasses –