Yunfeng's Simple Blog

Yunfeng's Simple Blog

马上订阅 Yunfeng's Simple Blog RSS 更新: https://vra.github.io/atom.xml

Python lru_cache 使用与源码解读

2025年1月29日 16:35

1. 用法说明

functools.cachefunctools.lru_cache都是Python标准库functools模块提供的装饰器,用于缓存函数的计算结果,以提高函数的执行效率。

举一个简单的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
from functools import lru_cache
import timeit

@lru_cache
def factorial(n):
return n * factorial(n-1) if n else 1

execution_time1 = timeit.timeit("factorial(64)", globals=globals(), number=10000)
execution_time2 = timeit.timeit("factorial.__wrapped__(64)", globals=globals(), number=10000)

print(f"Execution time1: {execution_time1:.4f} seconds")
print(f"Execution time2: {execution_time2:.4f} seconds")
print(f"Speedup: {execution_time2/execution_time1:.4f} times")

其中__wrapped__ 表示装饰器中原始的函数,也就是没有作用装饰器之前的裸函数。

代码输出如下:

1
2
3
Execution time1: 0.0004 seconds
Execution time2: 0.0016 seconds
Speedup: 3.5078 times

可以看到,通过lru_cache保存factorial函数的中间结果,得到了3.5倍的加速。
通过这里例子,我们可以看到lru_cache的使用方式,也是比较简单:

  1. import lru_cache:: from functoools import lru_cache
  2. 给函数添加@lru_cache装饰器。

通过查看源码,可以看到lru_cache函数签名如下:

1
def lru_cache(maxsize=128, typed=False):

其中maxsize 参数表示缓存的最多结果数,默认是128。如果计算结果超过128,则遵循Least-recently-used (LRU)原则,将最近使用次数最少的缓存结果替换为当前的结果。如果设置maxsize=None,则缓存无上限,但内存占用也可能会增大,使用时多观察。

typed参数表示是否按类型缓存不同变量,即使数值一样。例如typed=True,那么f(decimal.Decimal("3.0"))f(3.0)也会分开缓存。

2. 实际使用例子

上面只是一个玩具例子,实际代码中,lru_cache用法还是挺多的,这里举一些实际使用例子,来更清晰地理解它的功能。

2.1 get_available_devices

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@lru_cache()
def get_available_devices() -> FrozenSet[str]:
"""
Returns a frozenset of...

剩余内容已隐藏

查看完整文章以阅读更多