【python】functools.lru_cache自动缓存

基本介绍

lru_cache是Python3.2版本在functools标准模块中引入的装饰器,用于实现最近最少使用(Least Recently Used, LRU)缓存策略,适用于所有相同输入对应相同输出的确定性函数,即缓存函数的参数和返回值的映射,只要下次调用参数相同,就直接返回缓存的结果,不再执行函数体。

工作原理:

  • 缓存命中:当使用相同的参数调用被装饰的函数时,函数不会真正执行,而是直接从缓存中返回结果。
  • 缓存未命中:当参数不在缓存中时,函数正常执行,并将结果存入缓存。
  • 缓存淘汰:当缓存(不同参数个数)达到设定的最大容量(由 maxsize参数指定)时,它会自动淘汰最久未被使用的结果,以控制内存占用。

可通过参数maxsize=n指定缓存的最大容量,参数值为None表示无限制缓存,会缓存所有不同参数组合的函数返回值,性能最优但存在内存溢出的风险,根据实际情况设置。

在递归中的应用

lru_cache虽然适用于所有确定性的函数,但在递归场景中使用特别合适,因为递归场景中往往需要重复计算相同的子问题。以下面斐波那契数列为例:

def fib(num):
    if num == 0 or num == 1:
        return num
    return fib(num - 1) + fib(num - 2)

fib(5)对应的递归树:

               fib(5)
               /      \
          fib(4)      fib(3)
         /     \       /    \
     fib(3)  fib(2)  fib(2) fib(1)
    /    \    /   \   /   \
 fib(2) f(1) f(1)f(0) f(1)f(0)
 /   \
f(1) f(0)

如果不使用缓存,fib(3)和fib(2)都被重复计算了多次,如果把这棵递归树看成满二叉树,fib(n)一共有n层,每层的节点数量分别为 2 0 2^0 20, 2 1 2^1 21, 2 2 2^2 22, …, 2 n 2^n 2n, 那么总的时间复杂度 O ( 2 n ) O(2^n) O(2n)

如果使用了lru,函数会在第一次计算矩形标记的fib(0),fib(1),…, fib(5)时将每个参数对应的函数值缓存,也就是对于fib(5)的整个计算流程中,标记的6个记录在第一次计算时未命中缓存,会执行函数并将这6个记录的结果缓存,在后续计算中直接读取圆形标记的fib(1),fib(2),fib(3)的缓存,直接读取3次缓存就可以直接结束整个函数。
在这里插入图片描述
对于上面的分析可使用被装饰函数的cache_info方法输出详细的缓存信息查看:

from functools import lru_cache


@lru_cache(maxsize=None)
def fib(num):
    if num == 0 or num == 1:
        return num
    return fib(num - 1) + fib(num - 2)


print(fib(5))
print(fib.cache_info())

在这里插入图片描述

lru_cache装饰的函数也会自动同时绑定上cache_info方法,用于显示整个函数计算过程中的缓存命中情况,返回4个字段,含义分别是:
1)hits:缓存命中次数
2)misses:缓存未命中次数
3)maxsize:缓存最大容量
4)currsize:当前已缓存数量

缓存清空

lru_cache会为所有同名的函数全局维护一个独立的缓存结构,不同函数之间的缓存空间不冲突。除非手动cache_clear,否则缓存不会自动清除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值