PythiloLesson 13 of 15 · progress kept in this browser

Caching behind an interface

When a lookup is slow, wrap it rather than editing it. A caching wrapper has the same methods as the real implementation, holds it, and answers repeated requests from memory. Callers cannot tell the difference, and the slow code stays simple.

class SlowPrices:
    def price(self, sku):
        print("asking the slow service")
        return 3

class CachedPrices:
    def __init__(self, inner):
        self.inner = inner
        self.cache = {}

    def price(self, sku):
        if sku not in self.cache:
            p = self.inner.price(sku)
            self.cache[sku] = p
        return self.cache[sku]

cached = CachedPrices(SlowPrices())
print(cached.price("A"), cached.price("A"))
Your task

Write CachedPrices(inner, ttl, clock) whose price(sku) calls inner.price(sku) only when there is no entry for sku or the entry is at least ttl seconds old by clock(), and whose invalidate(sku) drops one entry, ignoring unknown skus. A price of 0 is cached like any other.