* kj:
In <mailman.1030.1269194878.23598.python-l...@python.org> Dennis Lee Bieber
<wlfr...@ix.netcom.com> writes:
On Sun, 21 Mar 2010 16:57:40 +0000 (UTC), kj <no.em...@please.post>
declaimed the following in gmane.comp.python.general:
Regarding properties, is there a built-in way to memoize them? For
example, suppose that the value of a property is obtained by parsing
the contents of a file (specified in another instance attribute).
It would make no sense to do this parsing more than once. Is there
a standard idiom for memoizing the value once it is determined for
the first time?
Pickle, Shelve? Maybe in conjunction with SQLite3...
I was thinking of something less persistent; in-memory, that is.
Maybe something in the spirit of:
@property
def foo(self):
# up for some "adaptive auto-redefinition"?
self.foo = self._some_time_consuming_operation()
return self.foo
...except that that assignment won't work! It bombs with "AttributeError:
can't set attribute".
Since foo is a read only property you can assign to it.
But it doesn't matter: if it worked technically it wouldn't give you what you're
after, the once-only evaluation.
A simple way to do that, in the sense of copying code and having it work, is to
use a generator that, after evaluating the expensive op, loops forever yielding
the resulting value.
A probably more efficient way, and anyway one perhaps more easy to understand,
is as follows:
<code>
from __future__ import print_function
class LazyEval:
def __init__( self, f ):
self._f = f
self._computed = False
@property
def value( self ):
if not self._computed:
self._value = self._f()
self._computed = True
return self._value
class HiHo:
def _expensive_op( self ):
print( "Expensive op!" )
return 42
def __init__( self ):
self._foo = LazyEval( self._expensive_op )
@property
def foo( self ):
return self._foo.value
o = HiHo()
for i in range( 5 ):
print( o.foo )
</code>
Cheers & hth.,
- Alf
--
http://mail.python.org/mailman/listinfo/python-list