如何在 Python 中记忆 属性?
How to memoize a property in Python?
考虑以下最小示例:
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
我想记住 sum
,这样如果 self.a
和 self.b
没有改变,那么我们就不需要继续重新计算 属性。
仅当 self.a
或 self.b
发生变化时才应重新计算 属性 -- 有没有简单的方法可以做到这一点?
也使用 a
和 b
的属性,并在设置器中清除缓存:
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
或者如果你想要更通用的东西,你也可以检查一下:
编辑:最近有人建议将 __init__
中的 self._sum = None
添加到 "avoid an error when accessing sum",但实际上没有必要 - __init__
调用 a.setter
,后者调用 _clearsum
,它设置 _sum
属性,因此保证 self._sum
将被创建。
有一个模块可以执行此操作。 Pypi link 此处: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
python3:
from functools import lru_cache as memoized
@property
@memoized(maxsize=1)
def sum(self):
return self.a + self.b
python 3.8
from functools import cached_property
@cached_property
def sum(self):
return self.a + self.b
考虑以下最小示例:
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
我想记住 sum
,这样如果 self.a
和 self.b
没有改变,那么我们就不需要继续重新计算 属性。
仅当 self.a
或 self.b
发生变化时才应重新计算 属性 -- 有没有简单的方法可以做到这一点?
也使用 a
和 b
的属性,并在设置器中清除缓存:
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
或者如果你想要更通用的东西,你也可以检查一下:
编辑:最近有人建议将 __init__
中的 self._sum = None
添加到 "avoid an error when accessing sum",但实际上没有必要 - __init__
调用 a.setter
,后者调用 _clearsum
,它设置 _sum
属性,因此保证 self._sum
将被创建。
有一个模块可以执行此操作。 Pypi link 此处: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
python3:
from functools import lru_cache as memoized
@property
@memoized(maxsize=1)
def sum(self):
return self.a + self.b
python 3.8
from functools import cached_property
@cached_property
def sum(self):
return self.a + self.b