一日一技:实现函数调用结果的 LRU 缓存

摄影:产品经理
在工程项目中,可能有一些函数调用耗时很长,但是又需要反复多次调用,并且每次调用时,相同的参数得到的结果都是相同的。在这种情况下,我们可能会使用变量或者列表来存放,例如:

resp_1 = get_resp(param=1)resp_2 = get_resp(param=2)resp_3 = get_resp(param=3)

但是,如果返回的结果占用内存比较大,我们每次调用都把结果存在内存里面,就会消耗大量内存。

于是,我们可以使用 LRU 算法:最近最常使用的参数生成的结果,我们存下来,下次遇到相同的参数时直接返回结果。而不常出现的参数,等到需要的时候再计算。计算完成后,也先存下来。但是如果缓存空间不够了,不常使用的会先删除。

LRU 的算法自己手动实现起来比较麻烦,但好在 Python 的 functions模块已经提供了现成的 lru_cache装饰器供我们使用。

首先我们写一个不带 lru 算法的程序:

import timeimport datetimedef say(name):print(f'你好:{name}')now = datetime.datetime.now()return nownow = say('kingname')print(f'现在时间为:{now}')time.sleep(10)now = say('产品经理')print(f'现在时间为:{now}')time.sleep(10)now = say('kingname')print(f'现在时间为:{now}')

运行效果如下图所示:

从运行结果可以看到,调用函数三次,第一次和第三次传入的参数都是 kingname,第二次传入的参数为 产品经理, 你好:kingname打印了两次, 你会:产品经理打印了一次。第二次打印的时间比第一次多了10秒,第三次打印的时间比第二次多了10秒。

现在我们把 LRU 缓存加上。

import timeimport datetimefrom functools import lru_cache@lru_cache(maxsize=32)def say(name):print(f'你好:{name}')now = datetime.datetime.now()return nownow = say('kingname')print(f'现在时间为:{now}')tie.sleep(10)now = say('产品经理')print(f'现在时间为:{now}')time.sleep(10)now = say('kingname')print(f'现在时间为:{now}')

从打印出来的结果可以看出,第三次调用 say函数的时候,传入的也是 kingname,但是函数根本没有运行,所以没有打印第二个 你好:kingname。并且第三个时间与第一个时间完全相同。说明第三次调用函数的时候,直接读取的缓存。

lru_cache(maxsize=128,typed=False)接收两个参数,第一个参数 maxsize表示最多缓存多少个结果,这个数字建议设置为2的幂。超出这个结果就会启用 LRU 算法删除不常用的数据。第二个参数 typed表示是否检查参数类型,默认为 False,如果设置为 True,那么参数 3和 3.0会被当做不同的数据处理。

由于 lru_cache底层是基于字典来实现的缓存,所以参数都必须是 hashable 的,否则会导致报错。

来源:https://www.icode9.com/content-4-773051.html

(0)

相关推荐

  • 一文搞懂Python装饰器

    一.前言 本不打算专门写文来讲装饰器的,但有不少粉丝问到了,自己查阅了一些网上的装饰器教程,发现讲的通俗易懂的不多,也有不少照搬的文章.所以我这里专门来讲一讲它. 个人在用的人工智能学习网站推荐给大家 ...

  • Python 中的函数装饰器和闭包

    函数装饰器可以被用于增强方法的某些行为,如果想自己实现装饰器,则必须了解闭包的概念. 装饰器的基本概念 装饰器是一个可调用对象,它的参数是另一个函数,称为被装饰函数.装饰器可以修改这个函数再将其返回, ...

  • 10 道 Java 泛型面试题

    10 道 Java 泛型面试题

  • 利用 Chrome 原生工具进行网页长截图 | 一日一技

    之前试用 Firefox Quantum 时,我最喜欢的特性之一就是其自带的截图功能.它不仅可以自动检测网页元素边界,还能轻松保存整个网页,十分方便. 后来由于扩展及习惯等原因,我又换回了 Chrom ...

  • 一日一技:在Python里面实现链式调用

    原创 kingname 未闻Code 摄影:产品经理 大学路的泰国菜 我们在使用Django的models查询数据库时,可以看到有这种写法: form app.models import XXXque ...

  • 一日一技:在 Python 中编写抽象类

    摄影:产品经理 游玩:产品经理&kingname 在极客时间某设计模式相关的课程中,某老师说 Python 不支持抽象类和接口. 但实际上,Python 支持抽象类. Python 自带的ab ...

  • 一日一技:如何将exe反编译成Python脚本

    今年年初的时候,我写了一篇:别再问我Python打包成exe了!(终极版),相信解决了不少小伙伴的Pyinstaller打包问题. 不过我最近遇到了一个问题,自己打包好的exe文件还在,但是Pytho ...

  • LRU缓存算法

    一.什么是缓存 这里说的缓存是一种广义的概念,在计算机存储层次结构中,低一层的存储器都可以看做是高一层的缓存.比如Cache是内存的缓存,内存是硬盘的缓存,硬盘是网络的缓存等等. 缓存可以有效地解决存 ...

  • 木子一日禅集锦(477)

    一日禅集锦(477) 转载摘录 妮子 雷瑊君 天涯社区 有人问禅师:"师父,怎样才能控制情绪,遇事不生气呢?"禅师:"世事无常,但因果不爽,若能深信因果,则不生迷惑,没有 ...

  • 重读缠论11:技术流之吻技,关于吻技如何获得高收益

    缠师之前的10章,更多的还是从概念上引导粉丝,对他的能力有一定的认知.之前十章,主要讲了心理.选股.如何看K线图,当时的大盘情况与介入时机等. 而从第11章开始,缠师作为BOSS级"神仙&q ...

  • 大爷的罗汉大虾,北京饭店名菜,50年如一日,老饭骨“厨”心不改

    大爷的罗汉大虾,北京饭店名菜,50年如一日,老饭骨“厨”心不改

  • 秦可卿如何同贾珍相处的?不仅一日换四五遍衣服,还在钱上打主意

    宁国府里的最大的丑闻发生在贾珍和儿媳秦可卿之间. 老仆人焦大醉骂之后,两人之间的事情也就传开了.但是两人之间的是非曲直,谁是谁非却始终是谜.秦可卿病死之说表明两人之间是清白的,而脂砚斋留下的" ...