If a function always returns the same result for the same arguments, and it's slow, there's no reason to work the answer out twice. functools.cache stores each result the first time and hands it back from then on.
Before
A recursive Fibonacci recomputes the same values over and over. Count how many calls it makes:
calls = 0 def fib(n): global calls calls += 1 return n if n < 2 else fib(n - 1) + fib(n - 2) print(fib(25), "in", calls, "calls")
75025 in 242785 calls
After
from functools import cache calls = 0 @cache def fib(n): global calls calls += 1 return n if n < 2 else fib(n - 1) + fib(n - 2) print(fib(25), "in", calls, "calls") print(fib(25), "in", calls, "calls") # asked again: answered from the cache print(fib.cache_info())
75025 in 26 calls 75025 in 26 calls CacheInfo(hits=24, misses=26, maxsize=None, currsize=26)
From 242,785 calls to 26: each value from 0 to 25 is worked out once.
Put a limit on it
cache keeps every result forever. For a function called with many different arguments, lru_cache(maxsize=...) keeps only the most recently used ones.
from functools import lru_cache @lru_cache(maxsize=2) def exchange_rate(currency): print(" looking up", currency) return {"EUR": 1.17, "USD": 1.33, "INR": 111.5}[currency] for c in ["EUR", "EUR", "USD", "INR", "EUR"]: exchange_rate(c) print(exchange_rate.cache_info())
looking up EUR looking up USD looking up INR looking up EUR CacheInfo(hits=1, misses=4, maxsize=2, currsize=2)
With room for two, looking up INR pushed EUR out, so the last EUR was fetched again.
Why it works
The decorator wraps the function in a dict keyed by the arguments. A call with arguments it has seen skips the body entirely.
When not to use it
Only on pure functions: same arguments, same answer, no side effects. Cache a function that reads the clock, a file or a database and it will keep returning the old answer. Arguments must be hashable, so a list argument raises TypeError: unhashable type. And an unbounded cache on a function called with endless distinct arguments is a memory leak; that's what maxsize is for.