Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   Re: lazy properties? (http://www.velocityreviews.com/forums/t954121-re-lazy-properties.html)

Cameron Simpson 11-01-2012 10:08 PM

Re: lazy properties?
 
On 01Nov2012 21:38, Andrea Crotti <andrea.crotti.0@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@zip.com.au>

Cordless hoses have been around for quite some time. They're called buckets.
- Dan Prener <prener@watson.ibm.com>


All times are GMT. The time now is 11:31 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.