Function decorator that caches function results
Lasse Vågsæther Karlsen
lasse at vkarlsen.no
Sat Oct 8 11:09:05 EDT 2005
jepler at unpythonic.net wrote:
> On Sat, Oct 08, 2005 at 01:53:28PM +0000, Duncan Booth wrote:
>
>>Unless the results stored in the cache are very large data structures, I
>>would suggest that you simply store (args,kwargs) as the cache key and
>>accept the hit that sometime you'll cache the same call multiple times.
>
>
> ... except that dicts cannot be dict keys
>
> Another 'memoize' decorator uses this to get the key:
> kw = kwargs.items()
> kw.sort()
> key = (args, tuple(kw))
> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/325905
>
> Jeff
Yeah, but as far as I can see it, this one too fails to recognize
situations where the function is called twice with essentially the same
values, except that in one call it uses named arguments:
k1 = fibonacci(100)
k2 = fibonacci(idx = 100)
this is essentially the same call, except the second one uses a named
argument, which means the function will be invoked and a second cache
entry will be stored.
Granted, not a big problem in most such cases, but here's my augmented
function. Bare in mind that I'm 2 weeks into Python so there's bound to
be room for improvement :)
def cache(fn):
cache = {}
arg_names = inspect.getargspec(fn)[0]
def cached_result(*args, **kwargs):
# If function is called without parameters, call it without
using the cache
if len(args) == 0 and len(kwargs) == 0:
return fn()
# Work out all parameter names and values
values = {}
for i in range(len(args)):
values[arg_names[i]] = args[i]
for key in kwargs:
values[key] = kwargs[key]
key = tuple([(key, value) for (key, value) in
sorted(values.iteritems())])
# Check cache and return cached value if possible
if key in cache:
return cache[key]
# Work out new value, cache it and return it
result = fn(*args, **kwargs)
cache[key] = result
return result
# Return wrapper function
return cached_result
--
Lasse Vågsæther Karlsen
http://usinglvkblog.blogspot.com/
mailto:lasse at vkarlsen.no
PGP KeyID: 0x2A42A1C2
More information about the Python-list
mailing list