Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #32576 > unrolled thread
| Started by | Cameron Simpson <cs@zip.com.au> |
|---|---|
| First post | 2012-11-02 09:08 +1100 |
| Last post | 2012-11-02 09:08 +1100 |
| Articles | 1 — 1 participant |
Back to article view | Back to comp.lang.python
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: lazy properties? Cameron Simpson <cs@zip.com.au> - 2012-11-02 09:08 +1100
| From | Cameron Simpson <cs@zip.com.au> |
|---|---|
| Date | 2012-11-02 09:08 +1100 |
| Subject | Re: lazy properties? |
| Message-ID | <mailman.3169.1351807702.27098.python-list@python.org> |
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>
Back to top | Article view | comp.lang.python
csiph-web