在 Python 标准库的 functools 模块中,有个 lru_cache 装饰器,用于为一个函数添加缓存系统:
- 存储函数的输入和对应的输出
- 当函数被调用,并且给出了已经缓存过的输入,那么函数不会再运行,而是直接从缓存中获取对应的输出
- 有两个可选参数
-
maxsize设置缓存的大小,设置后,缓存的大小就会被限制在这个值之内(缓存默认没有上限)- 当缓存达到上限时,最近最少使用的缓存会被移除
-
typed如果设置为True后,会根据输入参数的类型分别进行缓存(默认是False即不分类型)- 例如
1和1.0尽管在 Python 中是相等的,但是会被当成两个不同的输入进行缓存
- 例如
-
- 有两个方法用于清理和查看缓存
-
cache_clear()清空所有的缓存 -
cache_info()返回一个包含缓存状态的命名元组,包含以下几个字段-
hits缓存命中的次数 -
misses缓存未命中的次数 -
maxsize缓存的最大容量 -
currsize当前缓存的使用量
-
-
本质上,这个 lru_cache 装饰器是通过空间换取时间的方式来提高程序的性能,所以 lru_cache 装饰器并不适合所有的场景:
- 合适的场景
- 具有重复计算的递归函数
- 计算成本较高的函数
- 计算密集型或者需要大量重复计算的函数
- 不合适的场景
- 函数运行在内存有限的环境中
- 函数有大量的不同输入
- 函数有副作用,或者依赖于外部状态
通过下面的例子可以很好的理解 @lru_cache() 的用法:
from functools import lru_cache
@lru_cache()
def abc(name: str):
print(f'缓存 name = {name}')
return name
abc('1')
# 缓存 name = 1
# '1'
abc('2')
# 缓存 name = 2
# '2'
abc('3')
# 缓存 name = 3
# '3'
abc('1')
abc('2')
abc('3')
# '1'
# '2'
# '3'
abc.cache_info()
# CacheInfo(hits=3, misses=3, maxsize=128, currsize=3)
abc('3')
# '3'
abc.cache_info()
# CacheInfo(hits=4, misses=3, maxsize=128, currsize=3)
abc.cache_clear()
abc.cache_info()
# CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)