缓存超类中的属性 [英] Caching attributes in superclass
问题描述
例如,我有一个可以缓存某些值以避免多次计算它们的类
I have a class which caches some values to avoid computing them many times, for instance
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
仅被计算一次,并且所有其他时间都返回预计算值.到目前为止一切顺利.
In this way, self._value
is computed only once and all the other times the precomputed value is returned. So far so good.
现在,让我们假设我想用类B
子类化A
.在我们的例子中,类B
将具有自己的计算self._value
的方法,但有时需要A
的value
,如本例所示:
Now, let's suppose I want to subclass A
with class B
. In our case class B
will have its own method of computing self._value
but it sometimes will need A
's value
, like in this example:
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
现在,很明显的麻烦是,如果在value()
之前调用get_old_value()
,它将永远缓存A
的value
.如果以相同的方式在get_old_value()
之前调用value()
,则get_old_value()
实际上将始终返回value()
.
Now, clearly the trouble is that if get_old_value()
is called before value()
it will cache A
's value
forever. If value()
is called before get_old_value()
in the same way, get_old_value()
will actually always return value()
.
当然,在实现get_old_value()
的过程中,可以简单地使用A
的<complex code that produces value>
,但这将重复代码(这几乎会使子类无效),甚至将<complex code that produces value>
包裹在另一种方法中. A
并在get_old_value()
中调用该方法,但这根本不会使用缓存.
Of course, one could simply use A
's <complex code that produces value>
, in the implementation of get_old_value()
but that would duplicate code (which would pretty much make subclassing useless) or even wrap <complex code that produces value>
inside another method in A
and call that method in get_old_value()
but this would not use caching at all.
另一种方法可能是:
def get_old_value(self):
result = super().value
self._c = None
return result
,但这仍然会删除A
版本的value
的缓存,并且看起来一点也不干净.有没有更好的方法可以做到这一点?
but that would anyway remove caching for A
's version of value
and does not look clean at all. Is there any better way to accomplish this?
我想补充的一件事是,在我的代码中A
和B
对于超类和子类来说确实有意义,否则我会考虑使用组合.
One thing I want to add is that in my code A
and B
make really sense as superclass and subclass, otherwise I would consider composition.
推荐答案
您需要做的是使用名称修改-这将允许每个类/子类维护变量的私有版本,以免破坏彼此:
What you need to do is use name-mangling -- this will allow each class/subclass to maintain a private version of the variable so they don't clobber each other:
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
请注意,您现在还需要在B
的__init__
中设置__value
.
Please note you now need to set __value
in B
's __init__
as well.
另请参阅此答案,以获取更多有关名称处理的小知识.
See also this answer for a couple more tidbits about name-mangling.
这篇关于缓存超类中的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!