Pythonwikiには次のようなmemoizeデコレータが紹介されています。
# note that this decorator ignores **kwargs
def memoize(obj):
cache = obj.cache = {}
@functools.wraps(obj)
def memoizer(*args, **kwargs):
if args not in cache:
cache[args] = obj(*args, **kwargs)
return cache[args]
return memoizer
ただ、コメントに書いてあるとおり、kwargsには対応していない様子。では対応しましょう。
# do not use "self" for a name of argument.
import inspect
def memoize(obj):
cache = obj.cache = {}
@functools.wraps(obj)
def memoizer(*args, **kwargs):
argdict = inspect.getcallargs(obj, *args, **kwargs)
argdict.pop('self', None) # if obj is a bound method, arguments includes "self"
argset = frozenset(argdict.iteritems()) # for Python3, use dict.items() instead
if argset not in cache:
cache[argset] = obj(*args, **kwargs)
return cache[argset]
return memoizer
肝は、標準ライブラリのinspectを使うこと。
inspect.getcallargs()は
>>> def f(a, b, c=10):
... pass
...
>>> inspect.getcallargs(f, 1, 2)
{'a': 1, 'c': 10, 'b': 2}
みたいに、引数の名前と引数を辞書にしてくれます。
inspectは色々便利です。