[Python-ideas] caching properties
Steven D'Aprano
steve at pearwood.info
Thu Apr 30 15:56:48 CEST 2009
On Thu, 30 Apr 2009 10:36:17 pm Jeremy Banks wrote:
> I think one thing that should be addressed is how to change the
> cached value, for example after the setter is called.
For the use-case being discussed, you generally don't want to cache a
value that changes. You generally want to cache a value which is
expensive to calculate, but never changes.
However, there are uses for caches that expire after some time. I just
can't think of any where I'd want them to be accessed via a property
instead of a function call.
> Having multiple
> decorators would seem to make this slightly more complicated.
I don't see why. The cache decorator could expose an interface to expire
the cached value.
Here's a quick&dirty but working solution. (Tested under Python 2.5.)
def once(func):
class Cache(object):
def __call__(self, *args, **kwargs):
try:
return self._value
except AttributeError:
result = func(*args, **kwargs)
self._value = result
return result
def expire(self):
del self._value
return Cache()
class Test(object):
@property
@once
def expensive(self):
import time
time.sleep(20)
return 1
Works like a charm :) (At least for a solution I knocked up in 30
seconds.) The only downside is that to expire the cache, you need the
not-very-obvious call:
Test.expensive.fget.expire()
rather than t.expensive.expire(), which can't work for obvious reasons.
> If we
> were using only one, it would be easy to just add a cache property to
> the decorated function, which the setter could easily deal with.
...
> I guess this doesn't actually work anyway because of the way setters
> are specified, since it would refer to the setter instead of the
> property. Hmm.
I'm not exactly sure that a solution that doesn't work can be said
to "easily deal with" anything :)
--
Steven D'Aprano
More information about the Python-ideas
mailing list