
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