在计算机软件领域,缓存(Cache)指的是将部分数据存储在内存中,以便下次能够更快地访问这些数据,这也是一个典型的用空间换时间的例子。

functools 模块

如:

1. functools.cache

#python3.9 新增
@functools.cache(user_function)

返回值与 lru_cache(maxsize=None) 相同,创建一个查找函数参数的字典的简单包装器. 因为它不需要移出旧值,所以比带有大小限制的 lru_cache() 更小更快.

如,

from functools import cache

@cache
def factorial(n):
    print(f"[Cache]计算 {n} 的阶乘")
    return n * factorial(n-1) if n else 1

#没有缓存,计算11次递归调用
a = factorial(10)

#已有缓存,直接查询缓存结果
b = factorial(5)

#除了已有缓存,新增两次递归调用
c = factorial(12)

2. functools.lru_cache

一般用于缓存的内存空间是固定的,当有更多的数据需要缓存的时候,需要将已缓存的部分数据清除后再将新的缓存数据放进去。需要清除哪些数据,就涉及到了缓存置换的策略,其中,LRU(Least Recently Used,最近最少使用)是很常见的一个,也是 Python 中提供的缓存置换策略。

functools.lru_cache 函数是一个装饰器,为函数提供缓存功能。在下次以相同参数调用时直接返回上一次的结果,缓存 maxsize 组传入参数,用于节约高开销或I/O函数的调用时间.

@functools.lru_cache(maxsize=128, typed=False)
#若,maxsize=None,则LRU特性被禁用,且缓存可无线增长.

由于使用了字典存储缓存,所以该函数的固定参数和关键字参数必须是可哈希的。

lru_cache 修饰的函数在被相同参数调用的时候,后续的调用都是直接从缓存读结果,而不用真正执行函数。

from functools import lru_cache

def factorial(n):
  print(f"[No LRU_Cache]计算 {n} 的阶乘")
  return 1 if n <= 1 else n * factorial(n - 1)

@lru_cache
def factorial_lru(n):
  print(f"[LRU_Cache]计算 {n} 的阶乘")
  return 1 if n <= 1 else n * factorial_lru(n - 1)

#没有 LRU Cache,每次重新计算调用
a = factorial(5)
print(f'5! = {a}')
b = factorial(3)
print(f'3! = {b}')


#没有缓存,计算5次递归调用
a = factorial_lru(5)
print(f'5! = {a}')
#查看缓存信息
print(factorial_lru.cache_info())
#输出如:CacheInfo(hits=0, misses=5, maxsize=128, currsize=5)

#已有缓存,直接读取存储值
b = factorial_lru(3)
print(f'3! = {b}')

#清除缓存
factorial_lru.cache_clear()
print(factorial_lru.cache_info())
#输出如,CacheInfo(hits=0, misses=5, maxsize=128, currsize=5)

lru_cache缓存装饰器提供的功能有:

  • 缓存被装饰对象的结果(基础功能)
  • 获取缓存信息
  • 清除缓存内容
  • 根据参数变化缓存不同的结果
  • LRU算法当缓存数量大于设置的maxsize时清除最不常使用的缓存结果
Last modification:January 24th, 2022 at 02:41 pm