Skip to content

Instantly share code, notes, and snippets.

@nevir
Created February 3, 2011 00:37
Show Gist options
  • Save nevir/808824 to your computer and use it in GitHub Desktop.
Save nevir/808824 to your computer and use it in GitHub Desktop.
Memoizers for functions and methods!
import functools
def memoized(func):
"""
Decorator that caches the result of this INSTANCE METHOD call. Does not work for unbound methods.
Caches data in the attribute __memoized_cache__
>>> class Foo(object):
... @memoized
... def asdf(self):
... print('asdf once')
... return 'asdf'
...
>>> a = Foo()
>>> a.asdf()
asdf once
'asdf'
>>> a.asdf()
'asdf'
>>> class Bar(object):
... @memoized
... def fdsa(self, arg1, arg2):
... print('fdsa once for %d, %d' % (arg1, arg2))
... return arg1 + arg2
...
>>> b = Bar()
>>> b.fdsa(1, 2)
fdsa once for 1, 2
3
>>> b.fdsa(1, 2)
3
>>> b.fdsa(2, 1)
fdsa once for 2, 1
3
>>> b.fdsa(2, 3)
fdsa once for 2, 3
5
>>> c = Bar()
>>> c.fdsa(2, 3)
fdsa once for 2, 3
5
"""
CACHE_KEY = '__memoized_cache__'
def do_stuff(obj, *args):
cache = getattr(obj, CACHE_KEY, {})
key = (func.__name__, args)
try:
return cache[key]
except KeyError:
value = func(obj, *args)
cache[key] = value
setattr(obj, CACHE_KEY, cache)
return value
return do_stuff
# Gratefully stolen from http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
class unbound_memoized(object):
"""
Decorator that caches a function's return value each time it is called.
If called later with the same arguments, the cached value is returned, and
not re-evaluated.
This guy works for any method, instance or not. The cache has its own lifetime.
"""
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
try:
return self.cache[args]
except KeyError:
value = self.func(*args)
self.cache[args] = value
return value
except TypeError:
# uncachable -- for instance, passing a list as an argument.
# Better to not cache than to blow up entirely.
return self.func(*args)
def __repr__(self):
"""Return the function's docstring."""
return self.func.__doc__
def __get__(self, obj, objtype):
"""Support instance methods."""
return functools.partial(self.__call__, obj)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment