Python 内置缓存之@lru_cache

LRU算法原理

        LRU (Least Recently Used,最久未使用) 算法是一种缓存淘汰策略。其根据数据的历史访问记录来进行淘汰,核心思想是,“如果数据最近被访问过,那么将来被访问的几率也更高”。该算法最初为操作系统中一种内存管理的页面置换算法,主要用于找出内存中较久时间没有使用的内存块,将其移出内存从而为新数据提供空间。

Python中的LRU

        Python 中同样存在缓存机制,即内置模块functool 中的 lru_cache 装饰器,可以直接将函数或类方法的结果缓存住,后续调用则直接返回缓存的结果。用以节约高开销或I/O函数的调用时间。

@functools.lru_cache(maxsize=None, typed=False)
参数默认值说明
maxsize128如果 maxsize 设为 None,LRU 特性将被禁用且缓存可无限增长。设置为 2 的幂时,性能最佳。
typedFalse如果 typed 被设置为 true ,不同类型的函数参数将被分别缓存。 比如区分浮点数与整型。

注意事项:

        1、由于使用字典来缓存结果,因此传给该函数的位置和关键字参数必须为 hashable

        2、不同的参数模式可能会被视为具有单独缓存项的不同调用。 (缓存按照参数作为键)

案例:利用@lru_cache装饰器计算斐波那契数

        这里我们先写一个统计时间的装饰器,后面会用到。

import time

def show_time(func):
    def inner(*args,**kwargs):
        start_time = time.perf_counter()
        res = func(*args,**kwargs)
        end_time = time.perf_counter()
        print(f"The execution time: {end_time - start_time:.8f} seconds")
        return res
    return inner

        计算fibonacci(30)的时候很耗时,很多前面的fibonacci数在递归过程中会重复计算多次,耗时较长。

def fibonacci(num):
    return num if num < 2 else fibonacci(num - 1) + fibonacci(num - 2)

@show_time
def fib(n):
    return fibonacci(n)

print(fib(30))

# 输出:
# The execution time: 1.57796764 seconds
# 832040

        使用@lru_cache装饰器后,发现运行速度快了很多,因为使用了lru_cache则把之前执行的函数结果已经缓存了起来,就不需要再次执行了。

@lru_cache(maxsize=None)
def fibonacci(num):
    return num if num < 2 else fibonacci(num - 1) + fibonacci(num - 2)

@show_time
def fib(n):
    return fibonacci(n)

print(fib(30))

# 输出:
# The execution time: 0.00015267 seconds
# 832040

        通过上面的例子可以发现,当我们使用递归求斐波拉契数列 (斐波那契数列指的是这样一个数列:0,1,1,2,3,5,8,它从第3项开始,每一项都等于前两项之和) 的时候,缓存对性能的提升就尤其明显。

实际应用:如编写接口时缓存一些变动不大的数据如配置信息

        比如:缓存从数据库查询的用户信息,下次再调用这个接口时将直接返回用户信息列表而不需要重新执行一遍数据库查询逻辑,可以有效较少IO次数,加快接口反应速度。

@api.route("/user/info", methods=["POST"])
@login_required
@functools.lru_cache()
def add_user():
    user = UserInfo(name="李四")
    db.session.add(user)
    db.session.commit()
 
# 清除get_userinfo_list中的缓存
get_userinfo_list = current_app.view_functions["api.get_machine_list"]
cache_info = get_userinfo_list.__wrapped__.cache_info()
# cache_info 具名元组,包含命中次数 hits,未命中次数 misses ,最大缓存数量 maxsize 和 当前缓存大小 currsize
# 如果缓存数量大于0则清除缓存
if cache_info[3] > 0:
    get_userinfo_list.__wrapped__.cache_clear()
    return jsonify("新增用户成功")

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值