Lazy properties can be easily built in Python 2.4 -- properties whose value may require some effort to calculate, but whose values remain constant once calculated. This recipe uses decorators to implements such properties.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class Lazy(object):
def __init__(self, calculate_function):
self._calculate = calculate_function
def __get__(self, obj, _=None):
if obj is None:
return self
value = self._calculate(obj)
setattr(obj, self._calculate.func_name, value)
return value
# Sample use:
class SomeClass(object):
@Lazy
def someprop(self):
print 'Actually calculating value'
return 13
o = SomeClass()
o.someprop
o.someprop
|
In a recent discussion on comp.lang.python, there was discussion about how to provide properties which get calculated once, where you want to avoid the work of doing the calculation at all if you never use the property, but where you get simple access to the property once calculated. This technique evolved from a suggestion by Lief K-Brooks that looked to be something that could be made into an easy-to-use facility with decorators.
Elegant method to invalidate calculated value. Now, after one execution calc-function lost. It's interesting to add some method to invalidate and recalculate property.
Retracting a value is very simple. Just delete the attribute of the object. Using the sample above:
Or if you don't feel like implementing the Lazy descriptor:
Argh! Always test before you post (stupid me). The previous version's value was cached on the class, not the instance. Here's a version that works more like the original:
That's starting to get ugly. Oh, and the original solution is better if you need to invalidate the cached value. If you want to invalidate this one you'll need to invoke this incantation: