Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save basnijholt/3ef0c32abaabd5799673f377a727dae3 to your computer and use it in GitHub Desktop.
Save basnijholt/3ef0c32abaabd5799673f377a727dae3 to your computer and use it in GitHub Desktop.
Dynamically cache a method of an object once
import functools
import random
import time
import types
class A:
def f(self):
time.sleep(1)
return random.random()
def cache_once(obj):
"""Caches a method once."""
cache = {}
done = set([]) # args which already have been cached
@functools.wraps(obj)
def memoizer(*args, **kwargs):
self, *args = args
key = str(args) + str(kwargs)
if key in cache and key not in done:
# this is the only time we return a cached result
done.add(key)
return cache.pop(key)
else:
cache[key] = obj(*args, **kwargs)
return cache[key]
memoizer._cache = cache
memoizer._done = done
return memoizer
a = A()
a.f = types.MethodType(cache_once(a.f), a)
a.f() # takes 1s
a.f() # is cached
a.f() # takes 1s
a.f() # takes 1s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment