lru_cache是Python functools模块提供的LRU缓存装饰器,通过缓存函数的输入输出对避免重复计算,显著提升递归(如斐波那契)、纯函数、IO查询等场景性能;要求参数可哈希、无副作用、存在重复子问题,且可通过cache_info()验证命中率。

直接用 @functools.lru_cache() 就能显著加速多数纯函数式递归,但不是所有递归都适合——关键看参数是否可散列、是否有副作用、是否真存在重复子问题。
哪些递归函数加了 lru_cache 才有效
缓存只在「同一组输入反复出现」时起作用。如果每次递归调用的参数都不同(比如带时间戳、随机数、可变对象),缓存完全不生效,甚至因哈希开销拖慢速度。
- 适合的典型场景:
fibonacci(n)、levenshtein(s1, s2)、树形结构遍历中重复访问相同节点(如嵌套容器查找) - 不适合的场景:含
list或dict参数(不可散列)、函数内部修改全局状态、参数含datetime.now()等动态值 - 验证是否生效:加
@lru_cache()后调用func.cache_info(),看hits是否明显增长
lru_cache 的 maxsize 和 typed 怎么设
默认 maxsize=128 是保守值,对深度递归可能过早淘汰;typed=False 会让 1 和 1.0 被当成同一参数——这在数值计算中常是 bug 源头。
-
maxsize=None表示无限制缓存,适合子问题总数可控(如n ≤ 1000的 DP 问题) -
maxsize=256或512(2 的幂)比200更友好,LRU 驱逐逻辑更高效 - 涉及浮点与整数混用时,务必设
typed=True,否则fibonacci(5)和fibonacci(5.0)会互相污染缓存
为什么加了 lru_cache 还报 RecursionError
缓存只减少重复计算,不降低调用栈深度。如果原始递归深度超 Python 默认限制(约 1000 层),加缓存后依然会崩。
- 先用
sys.getrecursionlimit()查当前限制,必要时用sys.setrecursionlimit(3000)调高(慎用,可能引发段错误) - 更稳妥的做法是改写为迭代——例如把尾递归
factorial(n, acc)拆成 while 循环,彻底消除栈增长 - 注意:
lru_cache本身会略微增加单次调用开销(哈希 + 字典查表),极浅层递归(n )可能反而变慢
真正容易被忽略的是:缓存会持续持有对参数和返回值的引用,若参数含大对象(如长字符串、大型元组),可能导致内存无法及时释放。生产环境建议监控 cache_info().currsize 并结合业务设置合理 maxsize,而不是无脑设 None。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











