一、@cache装饰器的基本概念
@cache 是 python 3.9 引入的新功能,来源于标准库 functools 模块。它的作用是 对函数结果进行缓存(记忆化 memoization),从而避免重复计算,提高程序性能。
它的定义方式非常简单:
from functools import cache
@cache
def some_function(...):
...
当你用 @cache 修饰一个函数时,python 会将该函数的输入参数与计算结果自动保存到一个缓存(字典)中。当后续调用该函数且参数完全相同时,不会再次执行函数体的计算逻辑,而是直接返回之前缓存的结果。
二、工作原理
@cache 装饰器内部其实是基于 functools.lru_cache 实现的,它等价于:
from functools import lru_cache cache = lru_cache(maxsize=none)
也就是说:
- 无限大小缓存:
maxsize=none表示缓存结果没有数量限制,会根据需要一直增长(直到你的内存允许)。 - 键值匹配:缓存根据参数 值 判断是否命中(必须是可哈希类型,如数字、字符串、元组等)。
- 返回缓存结果:命中缓存时,直接返回结果而不执行函数计算。
三、使用示例
1. 基本示例:递归斐波那契数列
from functools import cache
@cache
def fib(n):
print(f"计算 fib({n})")
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(10)) # 第一次需要计算
print(fib(10)) # 第二次直接命中缓存,不会重新计算
运行效果:
- 第一次调用会完整计算
fib(10),输出多行"计算 fib(n)"的提示信息。 - 第二次调用相同参数,直接返回缓存值,不输出任何计算日志。
2. 模拟耗时计算
import time
from functools import cache
@cache
def slow_function(x):
print(f"开始计算 {x}...")
time.sleep(2) # 模拟耗时
return x * x
# 首次调用耗时
print(slow_function(5))
# 第二次调用相同参数时几乎立即返回
print(slow_function(5))
在实际场景中,如果一个函数计算代价高(如数据库查询、大文件解析、复杂计算等),使用 @cache 能显著减少重复工作。
四、注意事项
适用场景
- 适合纯函数(函数结果只依赖输入参数,且不会产生副作用)。
- 不适合需要每次实时更新的函数(例如获取当前时间、外部数据接口)。
参数限制
- 参数必须可哈希(hashable),如整数、字符串、元组等。
- 如果传入不可哈希类型(如列表、字典),会报错
typeerror: unhashable type。
内存占用
@cache默认缓存无限大小,可能造成内存占用增加;如果希望限制缓存大小,应使用lru_cache(maxsize=...)来控制。
缓存失效
@cache没有内置超时或自动失效机制,缓存会一直保留直到程序结束或手动清除:
your_function.cache_clear()
五、@cache与@lru_cache的区别
| 特性 | @cache | @lru_cache |
|---|---|---|
| 缓存大小限制 | 无限 (maxsize=none) | 可自定义 maxsize |
| 缓存策略 | 简单字典保存 | lru(least recently used)淘汰 |
| 用途 | 适合始终命中缓存且参数种类有限 | 适合缓存有限结果并自动淘汰旧数据 |
六、总结
@cache能让函数的重复调用变得快速,尤其适合计算昂贵且参数唯一性高的场景。- 它是
@lru_cache(maxsize=none)的简化版,功能单一但使用更简洁。 - 使用时需注意内存占用和参数类型,确保函数是“纯”的(无副作用)。
- 对于需要缓存大小控制的场景或更复杂的缓存管理,应使用
lru_cache。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论