Python 的 @lru_cache() 装饰器
在 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)