Python函数缓存机制_lru_cache应用说明【指导】

@lru_cache适用于纯函数的性能优化,基于LRU策略缓存结果;需满足参数可哈希、无副作用、不依赖外部状态,并合理设置maxsize以防内存膨胀。

@lru_cache 是 Python 标准库 functools 中提供的轻量级函数结果缓存装饰器,适用于**纯函数**(即相同输入总返回相同输出、无副作用)的性能优化场景。它基于最近最少使用(LRU)策略管理缓存,避免重复计算,尤其对递归、高频调用或耗时计算类函数效果显著。

什么时候该用 @lru_cache?

以下情况建议启用:

  • 函数被频繁调用,且参数组合有限(如斐波那契数列、树形结构遍历、解析固定格式字符串)
  • 函数内部有较重计算(如数值迭代、小规模查表、正则匹配预处理)但不涉及 I/O、全局状态或随机性
  • 你已确认函数是纯的——不修改外部变量、不依赖时间/文件/网络等外部状态
  • 内存可控:缓存容量默认不限(maxsize=None),但实际应设合理上限(如 @lru_cache(maxsize=128))防止内存膨胀

基础用法与常见配置

最简写法:

  from functools import lru_cache
  
  @lru_cache()
  def fib(n):
    if n
      return n
    return fib(n-1) + fib(n-2)

关键参数说明:

  • maxsize:缓存最大条目数。设为 None 表示无限制;设为整数(如 128)启用 LRU 驱逐;设为 0 相当于禁用缓存(仅用于调试开关)
  • typed:是否区分参数类型(如 fib(1)fib(1.0) 是否视为不同调用)。默认 False;设为 True 可提升类型敏感场景的准确性,但略增开销

必须注意的限制和陷阱

@lru_cache 不是万能加速器,踩坑点包括:

  • 不可缓存可变参数:若函数接受 listdict 等可变对象作为参数,会直接报 TypeError: unhashable type。解决方法是转成 tuplefrozenset,或改用其他缓存方案(如 functools.cached_property 或手动字典缓存)
  • 不跟踪内部状态变化:若函数依赖外部变量(如全局计数器、配置字典),缓存结果可能过期却不会自动更新
  • 线程安全但非进程安全:同一进程中多线程共享缓存,但多进程间不共享——需用 multiprocessing.Manager 或 Redis 等外部缓存替代
  • 无法缓存异常:抛出异常的调用不会被缓存,每次都会重新执行

查看和管理缓存状态

装饰后函数会新增两个实用方法:

  • func.cache_info():返回命名元组 CacheInfo(hits, misses, maxsize, currsize),可用于监控命中率
  • func.cache_clear():清空当前缓存,适合在配置变更、数据刷新后手动重置

例如:
  print(fib.cache_info())  # CacheInfo(hits=98, misses=10, maxsize=128, currsize=10)
  fib.cache_clear()