On Fri, Apr 20, 2012 at 9:57 AM, Rotwang <sg...@hotmail.co.uk> wrote: > As far as I know, the decorated function will always return the same value > as the original function. The problem is that the dictionary key stored > depends on how the function was called, even if two calls should be > equivalent; hence the original function gets called more often than > necessary. For example, there's this: > >>>> @memo > def f(x, y = None, *a, **k): > return x, y, a, k > >>>> f(1, 2) > (1, 2, (), {}) >>>> f.d > {((1, 2), ()): (1, 2, (), {})} >>>> f(y = 2, x = 1) > (1, 2, (), {}) >>>> f.d > {((1, 2), ()): (1, 2, (), {}), ((), (('y', 2), ('x', 1))): (1, 2, (), {})}
Using the FunctionMaker from the third-party decorator module [1]: from copy import copy import inspect from decorator import FunctionMaker memo_body = """ key = (%s) if key not in cache: cache[key] = func(%%(signature)s) return copy(cache[key]) """ def memo(func): (args, varargs, varkw, defaults) = inspect.getargspec(func) if varargs: args.append(varargs) if varkw: args.append("tuple(sorted(%s.items()))" % varkw) cache = {} decorated = FunctionMaker.create(func, memo_body % ', '.join(args), dict(func=func, cache=cache, copy=copy)) decorated.d = cache return decorated >>> @memo ... def f(x, y=None, *a, **k): ... return x, y, a, k ... >>> f(1, 2) (1, 2, (), {}) >>> f.d {(1, 2, (), ()): (1, 2, (), {})} >>> f(y=2, x=1) (1, 2, (), {}) >>> f.d {(1, 2, (), ()): (1, 2, (), {})} Cheers, Ian [1] http://pypi.python.org/pypi/decorator -- http://mail.python.org/mailman/listinfo/python-list