缓存超类中的属性 [英] Caching attributes in superclass

查看:82
本文介绍了缓存超类中的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,我有一个可以缓存某些值以避免多次计算它们的类

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的方法,但有时需要Avalue,如本例所示:

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(),它将永远缓存Avalue.如果以相同的方式在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?

我想补充的一件事是,在我的代码中AB对于超类和子类来说确实有意义,否则我会考虑使用组合.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆