[英]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.a
和self.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.a
或self.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:也使用a
和b
属性并清除 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.