Fix a function-cache key function, then make it durable
A small memoizing cache for arbitrary callables has a broken key function that mishandles positional versus keyword arguments and defaults. Fix the keying first, then extend the cache so entries survive a process restart and recover correctly.
- Level 1: fix the keying so every spelling of the same call shares one entry, different calls never do, and falsy results are cache hits.
- Level 2: make the cache survive a restart, and recover cleanly if the process died in the middle of a write.
import functools
def make_key(fn, args, kwargs, version="1", signature=None):
# Buggy: find every way this gets "the same call" wrong.
return hash((args, tuple(kwargs.items())))
class Cache:
def __init__(self, path=None, fsync=True):
self.data = {}
def get(self, key):
return self.data.get(key)
def put(self, key, value):
self.data[key] = value
def cached(cache=None, version="1"):
def decorate(fn):
store = cache if cache is not None else Cache()
@functools.wraps(fn)
def wrapper(*args, **kwargs):
key = make_key(fn, args, kwargs, version)
if store.get(key):
return store.get(key)
value = fn(*args, **kwargs)
store.put(key, value)
return value
wrapper.cache = store
return wrapper
return decorate
Sign in to see the worked answer
The full answer, chapter by chapter, with what interviewers expect at each level. Free with an account: one full answer per company.
