>>> def cache(func):
...     def wrapper(*args):
...         if args not in wrapper.cache:
...             wrapper.cache[args] = func(*args)
...         return wrapper.cache[args]
...     if not hasattr(wrapper, 'cache'):
...         wrapper.cache = {}
...     return wrapper
...
>>>
>>> @cache
... def add(a, b):
...     return a + b
...
>>>
>>> add(1,2)
3
>>>
>>> add(3,2)
5
>>> add(3,4)
7
>>>
>>> add(1,2)
3
>>>
>>>
>>> add.cache
{(1, 2): 3, (3, 2): 5, (3, 4): 7}