On 01Nov2012 21:38, Andrea Crotti <andrea.crott...@gmail.com> wrote: | Seeing the wonderful "lazy val" in Scala I thought that I should try to | get the following also in Python. | The problem is that I often have this pattern in my code: | | class Sample: | def __init__(self): | self._var = None | | @property | def var(self): | if self._var is None: | self._var = long_computation() | else: | return self._var | | | which is quite useful when you have some expensive attribute to compute | that is not going to change. | I was trying to generalize it in a @lazy_property but my attempts so far | failed, any help on how I could do that? | | What I would like to write is | @lazy_property | def var_lazy(self): | return long_computation() | | and this should imply that the long_computation is called only once..
I've got one of these which I use exactly as you wish above: def lazy_property(func): ''' A property whose access is controlled by a lock if unset. ''' lock_name = '_lock' prop_name = '_' + func.__name__ unset_object = None def getprop(self): ''' Attempt lockless fetch of property first. Use lock if property is unset. ''' p = getattr(self, prop_name) if p is unset_object: with getattr(self, lock_name): p = getattr(self, prop_name) if p is unset_object: ##debug("compute %s...", prop_name) p = func(self) ##warning("compute %s[%s].%s: %s", self, id(self), prop_name, type(p)) setattr(self, prop_name, p) return p return property(getprop) It computes the cached property name from the function name, but uses a global lock name "_lock" on the basis that the long_computation() will use shared state with the rest of the object. The microoptimisation of the lockless fetch may be either nonportable or pointless. I need to abstract this with a deeper level of nesting to support chaning lock_name, prop_name and unset_object if the caller desires, but for what you want it will work out of the box. I've got a similar thing that watches files for modification and reloads at need. Cheers, -- Cameron Simpson <c...@zip.com.au> Cordless hoses have been around for quite some time. They're called buckets. - Dan Prener <pre...@watson.ibm.com> -- http://mail.python.org/mailman/listinfo/python-list