functools.lru_cache 能显著加速重复调用的纯函数,核心要求是函数无副作用、参数可哈希;典型场景为斐波那契递归、动态规划等,设 maxsize=128 启用 lru 淘汰,maxsize=none 则无淘汰;缓存失效常见于参数含 list/dict 或函数含随机/时间操作。

直接结论:用 functools.lru_cache 能显著加速有重复参数调用的纯函数,但必须确保函数无副作用、参数可哈希,否则缓存会失效甚至引发隐蔽错误。
什么时候该加 @lru_cache?
典型场景是递归计算(如斐波那契)、动态规划子问题、或频繁调用且输入范围有限的纯函数。比如写一个计算第 n 项斐波那契数的函数,不加缓存时时间复杂度是指数级 O(2^n),加了之后变成 O(n)。
- 函数必须是确定性的:相同输入永远返回相同输出
- 参数类型必须全部可哈希(
int、str、tuple可以;list、dict、set不行) - 避免缓存过大:默认不限制大小,可能吃光内存,建议显式设
@lru_cache(maxsize=128)
maxsize=None 和 maxsize=128 差在哪?
maxsize 控制缓存条目上限。设为 None 表示无限制(实际是用字典实现,不淘汰),适合输入空间小且稳定的情况;设为具体数字(如 128)会启用 LRU 淘汰策略——最久未用的条目被踢出。
- 若函数参数组合远超
maxsize(比如有上万种不同输入),缓存命中率会断崖下跌 -
maxsize=1等价于只记最后一次调用结果,适合“最近一次状态”类逻辑 - 设为
0会禁用缓存(但装饰器仍存在,有轻微开销)
为什么加了 @lru_cache 却没提速?
常见原因不是装饰器没生效,而是函数本身不满足缓存前提。典型表现包括:
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
- 函数内部修改了全局变量或传入的可变对象(如
append()列表),导致看似相同输入实际行为不同 - 参数含
list或dict:会直接抛TypeError: unhashable type - 用了
datetime.now()、random.random()等非纯操作,每次结果都不同,缓存形同虚设 - 函数被多次重定义(比如在循环里动态生成),每个函数对象都是新实例,缓存互不共享
调试时可加 @lru_cache(maxsize=None) 后调用 func.cache_info() 查看 hits/misses 比例,低于 0.1 基本说明缓存没起作用。
替代方案:手动缓存 or cache(Python 3.9+)?
如果函数参数不可哈希,得自己转成可哈希形式(比如把 dict 改成 frozenset(dict.items())),但逻辑变重;或者改用 functools.cache(Python 3.9 引入),它是 lru_cache(maxsize=None) 的别名,语义更清晰,但没淘汰机制,内存风险更高。
-
@cache更适合配置解析、静态资源加载等输入固定、生命周期长的场景 - 需要淘汰策略时,必须用
@lru_cache(maxsize=...) - 注意
cache不兼容 Python lru_cache
缓存不是银弹——它把时间换空间,而空间失控比慢更难排查。上线前务必用真实数据压测 cache_info(),确认命中率和内存增长都在预期范围内。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










