When using @lru_cache avoid returning mutable, i.e. use tuples instead of lists.
E.g.
from functools import lru_cache
@lru_cache
def fib_lru(n):
# Fibonacci sequence
if n < 2:
res = [1, 1]
else:
res = fib_lru(n - 1)
res.append(res[-1] + res[-2])
return res
fib_lru(3) # [1, 1, 2, 3]
fib_lru(9) # [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
fib_lru(3) # [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] ! oops! previous state returned :(
fib_lru(11) # [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
fib_lru(9) # [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144] ! oops! previous state returned :(
# fix it by replacing lists with tuples
@lru_cache
def fib_lru_t(n):
if n < 2:
res = (1, 1)
else:
res = fib_lru_t(n - 1)
res = *res, res[-1] + res[-2]
return res
fib_lru_t(3) # (1, 1, 2, 3)
fib_lru_t(9) # (1, 1, 2, 3, 5, 8, 13, 21, 34, 55)
fib_lru_t(3) # (1, 1, 2, 3) OK!
fib_lru_t(11) # (1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144)
fib_lru_t(9) # (1, 1, 2, 3, 5, 8, 13, 21, 34, 55) OK!
Btw using `lru_cache` makes a real difference:
%timeit fib(100)
# 9.49 μs ± 151 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
%timeit fib_lru_t(100)
# 50.1 _ns_ ± 0.464 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)