lru_cache 是 functools 提供的 lru 缓存装饰器,用于纯函数避免重复计算;基于 ordereddict 实现 o(1) 查找与淘汰,支持 maxsize 和 typed 参数,需注意副作用、可哈希性及线程安全限制。

lru_cache 是什么,为什么用它
@lru_cache 是 Python 标准库 functools 中提供的一个装饰器,用于自动为函数添加**最近最少使用(LRU)缓存机制**。它的核心作用是:当函数被重复调用且参数相同时,直接返回之前计算过的结果,跳过实际执行,从而提升性能。
特别适合用在「纯函数」上——即相同输入永远返回相同输出、且无副作用(不修改全局变量、不读写文件、不发网络请求等)的函数。比如递归求斐波那契数、解析固定字符串、查配置表等场景。
底层原理:字典 + 双向链表 + 哈希键
LRU 缓存需要两个关键能力:快速查找(O(1))和高效淘汰最久未用项(O(1))。Python 的 lru_cache 通过以下方式实现:
- 内部维护一个有序字典(
OrderedDict),按访问顺序保存(key, value)对;新访问或新增时移到末尾,最久未用的总在开头 - 每次调用函数前,将参数用
hash()和repr()等方式生成唯一缓存键(key),不可哈希类型如list、dict会报错,可改用tuple或开启typed=True区分不同数值类型 - 命中缓存时,把对应 key 移到 OrderedDict 末尾(标记为“刚用过”);容量满时,弹出开头的 key-value 对
常用用法与参数详解
基本写法很简单:
立即学习“Python免费学习笔记(深入)”;
from functools import lru_cache <p>@lru_cache(maxsize=128) # maxsize=None 表示无限制;maxsize=0 表示禁用缓存 def fib(n): if n < 2: return n return fib(n-1) + fib(n-2)
关键参数说明:
-
maxsize:缓存最多保存多少个结果,默认 128;设为
None表示不限大小(慎用,可能内存溢出);设为0完全不缓存(但装饰器仍生效,仅用于统计) -
typed:是否区分参数类型,例如
fib(1)和fib(1.0)默认视为同一调用(因 hash 相同),设为True后会分别缓存
还可通过函数属性查看运行状态:
print(fib.cache_info()) # 返回 CacheInfo(hits=..., misses=..., maxsize=..., currsize=...) fib.cache_clear() # 清空缓存
实战注意点与避坑指南
虽然方便,但误用容易引发问题:
- 不可缓存带副作用的函数:比如函数里写了日志、修改了全局列表、调用了 time.time(),缓存后这些操作会被跳过,行为异常
-
避免缓存可变对象作为参数:如
@lru_cache修饰接收list的函数会失败(list 不可哈希),应转成tuple或改用其他缓存方案 - 线程安全但非进程安全:lru_cache 在多线程下可用(内部加了锁),但在多进程(如 multiprocessing)中各进程有独立缓存,不共享
-
递归函数慎用大 maxsize:深度递归可能快速占满缓存,建议配合
sys.setrecursionlimit()和监控cache_info()使用
一个小技巧:对类方法加缓存,需配合 @staticmethod 或把逻辑抽到模块级函数,因为默认绑定实例(self)会导致每次 self 不同而无法命中。










