Published: 15 December 2020, 18:00
Decorator functools.lru_cache caches the function result based on the given arguments:
from functools import lru_cache
@lru_cache(maxsize=32)
def say(phrase):
print(phrase)
return len(phrase)
say('hello')
# hello
# 5
say('pythonetc')
# pythonetc
# 9
# the function is not called, the result is cached
say('hello')
# 5
The only limitation is that all arguments must be hashable:
say({})
# TypeError: unhashable type: 'dict'
The decorator is useful for recursive algorithms and costly operations:
@lru_cache(maxsize=32)
def fib(n):
if n <= 2:
return 1
return fib(n-1) + fib(n-2)
fib(30)
# 832040
Also, the decorator provides a few helpful methods:
fib.cache_info()
# CacheInfo(hits=27, misses=30, maxsize=32, currsize=30)
fib.cache_clear()
fib.cache_info()
# CacheInfo(hits=0, misses=0, maxsize=32, currsize=0)
# Introduced in Python 3.9:
fib.cache_parameters()
# {'maxsize': None, 'typed': False}
And the last thing for today, you’ll be surprised how fast lru_cache
is:
def nop():
return None
@lru_cache(maxsize=1)
def nop_cached():
return None
%timeit nop()
# 49 ns ± 0.348 ns per loop
# cached faster!
%timeit nop_cached()
# 39.3 ns ± 0.118 ns per loop