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.
The property should only be recalculated when either self.a
or self.b
has changed -- is there an simple way to do this?
Use properties for a
and b
too and clear up your cache in the setters:
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.