[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