Created
January 25, 2012 20:30
-
-
Save patricklucas/1678540 to your computer and use it in GitHub Desktop.
LRU cache decorator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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