lazy properties?
Cameron Simpson
cs at zip.com.au
Thu Nov 1 18:08:09 EDT 2012
On 01Nov2012 21:38, Andrea Crotti <andrea.crotti.0 at 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 <cs at zip.com.au>
Cordless hoses have been around for quite some time. They're called buckets.
- Dan Prener <prener at watson.ibm.com>
More information about the Python-list
mailing list