Skip to content

Instantly share code, notes, and snippets.

@codysoyland
Created January 2, 2010 23:58
Show Gist options
  • Save codysoyland/267733 to your computer and use it in GitHub Desktop.
Save codysoyland/267733 to your computer and use it in GitHub Desktop.
import functools
class memoize(object):
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
return self.cache_get(args, lambda: self.func(*args))
def __get__(self, obj, objtype):
return self.cache_get(obj, lambda: self.__class__(functools.partial(self.func, obj)))
def cache_get(self, key, gen_callback):
try:
return self.cache[key]
except KeyError:
self.cache[key] = gen_callback()
return self.cache[key]
class Adder(object):
@memoize
def add(self, arg1, arg2):
print 'CALCULATING', arg1, '+', arg2
return arg1 + arg2
@memoize
def subtract(arg1, arg2):
print 'CALCULATING', arg1, '-', arg2
return arg1 - arg2
def main():
print subtract(10, 5)
print subtract(10, 5)
adder1 = Adder()
adder2 = Adder()
print adder1.add(5, 5)
print adder1.add(5, 5)
print adder2.add(5, 5)
print adder2.add(5, 5)
if __name__ == '__main__':
main()
@codysoyland
Copy link
Author

Thanks for the comment. I should note that the cache never gets cleaned, therefore never dereferences any object that has run any of its memoized methods. So if your application is long-running and creates lots of objects, they will never get garbage-collected. This caveat applies to all memoization decorators I know of (for example calling a memoized function with objects as arguments), but ideally a method-memoization decorator would clear the cache for any object that is garbage-collected. The only way I know to do this would be to store the cached result dictionary on each object in a unique attribute.

@codysoyland
Copy link
Author

At first glance, it looks like this one does the right thing (doesn't store object references): http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/

@dpo
Copy link

dpo commented Sep 16, 2011

I'm trying to understand your memoize example. From the point of view of being able to wrap both plain functions and class methods, what exactly does it do that http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize doesn't?
(I'm still learning decorators and descriptors, so please bear with me.)

@andrep
Copy link

andrep commented Sep 16, 2011 via email

@dpo
Copy link

dpo commented Sep 16, 2011

Thanks for the response. While trying to work this out I wrote my own, pieced together from various sources and my understanding of how things work. One thing I wanted to do is cache numpy arrays by computing their sha1 digest. My code is at https://gist.github.com/1222577. I'd be interested in any comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment