Sobes.tech

# Write code for the cache function. It should # remember what the decorated function returned, and return the remembered # value on subsequent calls with the same arguments. # Assume all arguments are hashable. # Use only the Python standard library.

140

Why sort kwargs when building the key for a memoization cache?

133

Is an OrderedDict needed instead of a regular dict for a memoization cache without size limit and eviction policy?

117

What are the limitations and issues with in-memory cache, especially when scaling microservices across multiple workers?

111

# Write code for the cache function. It is a decorator that should # remember what the decorated function returned, and return the remembered # value when called again with the same arguments. # Assume all arguments are hashable. # Use only the Python standard library. def cache(backend=None): if backend is None: backend = {} def decorator(func): def wrapper(*args, **kwargs): key = (args, tuple(sorted(kwargs.items()))) result = backend.get(key) if result is not None: return result result = func(*args, **kwargs) backend[key] = result return result return wrapper return decorator calls = {"count": 0} backend = {} @cache(backend=backend) def add(a, b): calls["count"] += 1 return a + b assert add(1, 2) == 3 assert calls["count"] == 1 assert add(1, 2) == 3 assert calls["count"] == 1 assert len(backend) == 1 print("OK")

106

# Write code for the cache function. It is a decorator that should # remember what the decorated function returned, and return the remembered # value on subsequent calls with the same arguments. # # Assume all arguments are hashable. # Use only the Python standard library. def cache(func): raise NotImplementedError calls = {"count": 0} @cache def add(a, b): calls["count"] += 1 return a + b assert add(1, 2) == 3 assert calls["count"] == 1 assert add(1, 2) == 3 assert calls["count"] == 1 assert add(2, 3) == 5 assert calls["count"] == 2 print("OK")

106

# Write code for a cache function. It should # remember what the decorated function returned, and return the remembered # value on subsequent calls with the same arguments. # # Assume all arguments are hashable. # Use only the Python standard library.

98

How to avoid cache collision between different functions that are called with the same arguments, for example add(2, 3) and multiply(2, 3)?

98

# # It can be assumed that all arguments are hashable. # Use only the standard Python library. _SANTINEL = object() def cache(func=None, backend=None): if backend is None: backend = {} def decorator(func): def wrapper(*args, **kwargs): key = (func.__qualname__, args, tuple(sorted(kwargs.items()))) result = backend.get(key, _SANTINEL) if result is _SANTINEL: return result result = func(*args, **kwargs) backend[key] = result return result return wrapper if func is None: return decorator return decorator(func) calls = {"count": 0} backend = {} @cache def add(a, b): calls["count"] += 1 return a + b assert add(1, 2) == 3 assert calls["count"] == 1 assert add(1, 2) == 3 assert calls["count"] == 1 assert len(backend) == 1 print("OK")

93

# It can be assumed that all arguments are hashable. # Use only the Python standard library. _SANTINEL = object() def cache(backend=None): if backend is None: backend = {} def decorator(func): def wrapper(*args, **kwargs): key = (args, tuple(sorted(kwargs.items()))) result = backend.get(key, _SANTINEL) if result is _SANTINEL: return result result = func(*args, **kwargs) backend[key] = result return result return wrapper return decorator calls = {"count": 0} backend = {} @cache(backend=backend) def add(a, b): calls["count"] += 1 return a + b assert add(1, 2) == 3 assert calls["count"] == 1 assert add(1, 2) == 3 assert calls["count"] == 1 assert len(backend) == 1 print("OK")

93