简体   繁体   English

如何在 Python 中记住一个属性?

[英]How to memoize a property in Python?

Consider the following minimal example:考虑以下最小示例:

class Foo(object):

    def __init__(self):
        self.b = self.a = 1

    @property
    def sum(self):
        print 'Recalculating sum'
        return self.a + self.b

foo = Foo()
print foo.sum
print foo.sum   # Prints 'Recalculating sum' even though neither a or b has changed since previous call
foo.a = 2
print foo.sum   # a has been changed to 2 so recalculation is necessary

I would like to memoize sum such that if self.a and self.b doesn't change, then we don't need to keep recalculating the property.我想self.a sum以便如果self.aself.b没有改变,那么我们不需要继续重新计算属性。

The property should only be recalculated when either self.a or self.b has changed -- is there an simple way to do this?仅当self.aself.b发生变化时才应重新计算该属性——有没有一种简单的方法可以做到这一点?

python3:蟒蛇3:

from functools import lru_cache as memoized

@property
@memoized(maxsize=1)
def sum(self):
    return self.a + self.b

python 3.8蟒蛇 3.8

from functools import cache

@cached_property
def sum(self):
    return self.a + self.b

Use properties for a and b too and clear up your cache in the setters:也使用ab属性并清除 setter 中的缓存:

class Foo(object):

    def __init__(self):
        self.a = 1
        self.b = 1

    @property
    def a(self):
        return self._a

    @a.setter
    def a(self, value):
        self._a = value
        self._clearsum()

     @property
    def b(self):
        return self._b

    @b.setter
    def b(self, value):
        self._b = value
        self._clearsum()

    def _clearsum(self):
        self._sum = None

    @property
    def sum(self):
        if self._sum is None:
            self._sum = self.a + self.b
        return self._sum

Or if you want something a bit more generic, you can check this too: Storing calculated values in an object或者如果你想要更通用的东西,你也可以检查这个: 在对象中存储计算值

Edit : someone recently suggested adding self._sum = None in __init__ to "avoid an error when accessing sum", but that's actually not necessary - __init__ invokes a.setter , which invokes _clearsum , which sets the _sum attribute, so it's garanteed self._sum will be created whatever.编辑:最近有人建议在__init__添加self._sum = None以“避免访问 sum 时出现错误”,但这实际上不是必需的 - __init__调用a.setter ,它调用_clearsum ,它设置_sum属性,所以它是保证self._sum将被创建。

there is a module that does this.有一个模块可以做到这一点。 Pypi link here: https://pypi.org/project/memoized-property/ For the above code I have this with using the module: Pypi 链接在这里: https://pypi.org/project/memoized-property/对于上面的代码,我使用模块有这个:

In [2]: from memoized_property import memoized_property                                                                                                       

In [3]: class test():  
   ...:         def __init__(self):  
   ...:             self.a = 0  
   ...:             self.b = 0  
   ...:        @memoized_property  
   ...:        def sum(self):  
   ...:           print('calculating...')  
   ...:           return self.a + self.b  

In [4]: t=test()                                                                                                                                              

calculating...
In [5]: t.sum                                                                                                                                                 
Out[5]: 0

In [7]: t.a=5                                                                                                                                                 

In [8]: t.sum                                                                                                                                                 
Out[8]: 0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM