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