Skip to content

Instantly share code, notes, and snippets.

@patricklucas
Created January 25, 2012 20:30
Show Gist options
  • Save patricklucas/1678540 to your computer and use it in GitHub Desktop.
Save patricklucas/1678540 to your computer and use it in GitHub Desktop.
LRU cache decorator
def LRUCache(max_size):
"""A simple dict-based LRU cache
The cached function must:
- Have no kwargs
- Have only hashable args
- If the decorated function is passed an unhashable arg, a TypeError
will be raised
- Be idempotent (be without side effects)
- Otherwise the cache could become invalid
Usage:
@LRUCache(max_size=50)
def to_be_cached(foo, bar):
... some computation ...
return retval
"""
cache = {}
cache_keys = []
def lrucache_dec(fn):
def cached_fn(*args):
# args is a tuple, so it can be used as a dict key
if args in cache:
# Set args as most-recently-used
del cache_keys[cache_keys.index(args)]
cache_keys.append(args)
return cache[args]
# If fn(*args) raises an exception, the cache will not be affected,
# so no special measures need be taken.
retval = fn(*args)
# Add to the cache and set as most-recently-used
cache[args] = retval
cache_keys.append(args)
# Prune the cache if necessary
if len(cache_keys) > max_size:
del cache[cache_keys[0]]
del cache_keys[0]
return retval
return cached_fn
return lrucache_dec
if __name__ == '__main__':
@LRUCache(5)
def to_be_cached(foo, bar):
print "Computing for %r, %r" % (foo, bar)
return foo * 1000 + bar * 100
print to_be_cached(3, 5)
print to_be_cached(4, 5)
print to_be_cached(5, 5)
print to_be_cached(6, 5)
print "== (3, 5) cached, so no computation =="
print to_be_cached(3, 5)
print to_be_cached(7, 5)
print "== Evicts (4, 5) =="
print to_be_cached(8, 5)
print to_be_cached(4, 5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment