我的编程空间,编程开发者的网络收藏夹
学习永远不晚

python自带缓存lru_cache用法及扩展的使用

短信预约 信息系统项目管理师 报名、考试、查分时间动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

python自带缓存lru_cache用法及扩展的使用

目录
  • 1. lru_cache的使用
    • 1.1 参数详解
    • 1.2 基本用法
    • 1.3 进阶用法
  • 2. functiontools.wrap装饰器对lru_cache的影响
    • 2.1 多个装饰器装饰同一函数时的执行顺序
    • 2.2 functiontools.wrap原理
    • 2.3 使用wrap装饰器前后的变化
  • 3. 自制简易的my_cache
    • 3.1 lru_cache提供的功能
    • 3.2 cache的核心部件
    • 3.3 my_cache的实现
  • 4. lru_cache缓存和redis缓存的区别
    • 5. 总结

      本篇博客将结合python官方文档和源码详细讲述lru_cache缓存方法是怎么实现, 它与redis缓存的区别是什么, 在使用时碰上functiontools.wrap装饰器时会发生怎样的变化,以及了解它给我们提供了哪些功能然后在其基础上实现我们自制的缓存方法my_cache。

      1. lru_cache的使用

      1.1 参数详解

      以下是lru_cache方法的实现,我们看出可供我们传入的参数有2个maxsize和typed,如果不传则maxsize的默认值为128,typed的默认值为False。其中maxsize参数表示是的被装饰的方法最大可缓存结果数量, 如果是默认值128则表示被装饰方法最多可缓存128个返回结果,如果maxsize传入为None则表示可以缓存无限个结果,你可能会疑惑被装饰方法的n个结果是怎么来的,打个比方被装饰的方法为def add(a, b):当函数被lru_cache装饰时,我们调用add(1, 2)和add(3, 4)将会缓存不同的结果。如果 typed 设置为true,不同类型的函数参数将被分别缓存。例如, f(3) 和 f(3.0) 将被视为不同而分别缓存。

      
      def lru_cache(maxsize=128, typed=False):
          if isinstance(maxsize, int):
              if maxsize < 0:
                  maxsize = 0
          elif maxsize is not None:
              raise TypeError('Expected maxsize to be an integer or None')
      
          def decorating_function(user_function):
              wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
              return update_wrapper(wrapper, user_function)
      
          return decorating_function
      
      

      1.2 基本用法

      在我们编写接口时可能需要缓存一些变动不大的数据如配置信息,我们可能编写如下接口:

      
      @api.route("/user/info", methods=["GET"])
      @functools.lru_cache()
      @login_require
      def get_userinfo_list():
          userinfos = UserInfo.query.all()
          userinfo_list = [user.to_dict() for user in userinfos]
          return jsonify(userinfo_list)
      

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

      1.3 进阶用法

      还是以上面的例子,如果发生用户的删除或者新增时,我们再请求用户接口时仍然返回的是缓存中的数据,这样返回的信息就和我们数据库中的数据就会存在差异,所以当发生用户新增或者删除时,我们需要清除原先的缓存,然后再请求用户接口时可以重新加载缓存。

      
      @api.route("/user/info", methods=["POST"])
      @functools.lru_cache()
      @login_require
      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.cache_info()
          # cache_info 具名元组,包含命中次数 hits,未命中次数 misses ,最大缓存数量 maxsize 和 当前缓存大小 currsize
          # 如果缓存数量大于0则清除缓存
          if cache_info[3] > 0:
           get_userinfo_list.cache_clear()
          return jsonify("新增用户成功")
      

      在上面这个用法中我们,如果我们把lru_cache装饰器和login_require装饰器调换位置时,上述的写法将会报错,这是因为login_require装饰器中用了functiontools.wrap模块进行装饰导致的,具原因我们在下节解释, 如果想不报错得修改成如下写法。

      
      @api.route("/user/info", methods=["POST"])
      @login_require
      @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("新增用户成功")
      

      2. functiontools.wrap装饰器对lru_cache的影响

      在上节我们看到,因为@login_require和@functools.lru_cache()装饰器的顺序不同, 就导致了程序是否报错, 其中主要涉及到两点:

      • login_require装饰器中是否用了@functiontools.wrap()装饰器
      • @login_require和@functools.lru_cache()装饰器的执行顺序问题

      当我们了解完这两点后就可以理解上述写法了。

      2.1 多个装饰器装饰同一函数时的执行顺序

      这里从其他地方盗了一段代码来解释一下,如下:

      
      def decorator_a(func):
          print('Get in decorator_a')
          def inner_a(*args,**kwargs):
              print('Get in inner_a')
              res = func(*args,**kwargs)
              return res
          return inner_a
      
      def decorator_b(func):
          print('Get in decorator_b')
          def inner_b(*args,**kwargs):
              print('Get in inner_b')
              res = func(*args,**kwargs)
              return res
          return inner_b
      
      
      @decorator_b
      @decorator_a
      def f(x):
          print('Get in f')
          return x * 2
      
      f(1)

      输出结果如下:

      'Get in decorator_a'
      'Get in decorator_b'
      'Get in inner_b'
      'Get in inner_a'
      'Get in f'

      是不是很像django中的中间件的执行顺序,其实原理都差不多。

      2.2 functiontools.wrap原理

      引用其他博主的描述:

      Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,Python的functools包中提供了一个叫wraps的decorator来消除这样的副作用。写一个decorator的时候,最好在实现之前加上functools的wrap,它能保留原有函数的名称和docstring。

      补充:为了访问原函数此函数会设置一个__wrapped__属性指向原函数, 这样就可以解释上面1.3节中我们的写法了。

      2.3 使用wrap装饰器前后的变化

      未完待续。。。。。。。。。

      3. 自制简易的my_cache

      3.1 lru_cache提供的功能

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

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

      ​ 从列出的功能可知,python自带的lru_cache缓存方法可以满足我们日常工作中大部分需求, 可是它不包含一个重要的特性就是,超时自动删除缓存结果,所以在我们自制的my_cache中我们将实现缓存的超时过期功能。

      3.2 cache的核心部件

      在作用域内存在一个相对全局的字典变量cache={}

      在作用域内设置相对全局的变量包含命中次数 hits,未命中次数 misses ,最大缓存数量 maxsize和 当前缓存大小 currsize

      第二点中的缓存信息中增加缓存加入时间和缓存有效时间

      3.3 my_cache的实现

      待实现。。。。。。。。。。。。

      4. lru_cache缓存和redis缓存的区别

      比较类型 lru_cache redis
      缓存类型 缓存在app进程内存中 缓存在redis管理的内存中
      分布式 只缓存在单个app进程中 可做分布式缓存
      数据类型 hash 参数作为key,返回结果为value 有5种类型的数据结构
      适用场景 比较小型的系统、单体应用 常用的缓存解决方案
      功能 缓存功能但是缺少过期时间控制,但是使用上更加便捷 具备缓存需要的各种要素

      5. 总结

      综上所述,python自带的缓存功能使用于稍微小型的单体应用。优点是可以很方便的根据传入不同的参数缓存对应的结果, 并且可以有效控制缓存的结果数量,在超过设置数量时根据LRU算法淘汰命中次数最少的缓存结果。缺点是没有办法对缓存过期时间进行设置。

      到此这篇关于python自带缓存lru_cache用法及扩展的使用的文章就介绍到这了,更多相关python自带缓存lru_cache内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

      免责声明:

      ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

      ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

      python自带缓存lru_cache用法及扩展的使用

      下载Word文档到电脑,方便收藏和打印~

      下载Word文档

      猜你喜欢

      python自带缓存lru_cache用法及扩展的使用

      目录1. lru_cache的使用1.1 参数详解1.2 基本用法1.3 进阶用法2. functiontools.wrap装饰器对lru_cache的影响2.1 多个装饰器装饰同一函数时的执行顺序2.2 functiontools.wra
      2022-06-03

      python中自带缓存lru_cache怎么用

      这篇文章给大家分享的是有关python中自带缓存lru_cache怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1. lru_cache的使用1.1 参数详解以下是lru_cache方法的实现,我们看出可供
      2023-06-20

      Win10 2004系统自带清理缓存的使用方法

      这篇文章主要介绍了Win10 2004系统自带清理缓存的使用方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Win10 2004系统自带清理缓存的使用方法1、我们点击桌面左
      2023-06-10

      wordpress自带的缓存功能使用介绍

      用静态化当然可以解决这些问题,不过对于流量不大的博客就没必要了。 wordpress自带有缓存体系,关键的函数你可以在wp-includes/cache.php或 Codex里查找到所有的函数。 你可以使用下列函数来实现添加缓存。复制代码代
      2022-06-12

      Android的HTTP扩展包OkHttp中的缓存功能使用方法解析

      OkHttp 可以对 HTTP 响应的内容在磁盘上进行缓存。在进行 HTTP 请求时,如果该请求的响应已经被缓存而且没有过期,OkHttp 会直接使用缓存中的响应内容,而不需要真正的发出 HTTP 请求到远程服务器。在创建缓存时需要指定一个
      2022-06-06

      如何使用PHP开发缓存提高网站的可扩展性

      网站的可扩展性是非常重要的,尤其是在大流量网站中。为了提升网站的性能和稳定性,使用缓存是很常见的一种方法。在PHP开发中,我们可以使用各种缓存技术来提高网站的可扩展性。本文将详细介绍如何使用PHP开发缓存提高网站的可扩展性,并提供具体的代码
      如何使用PHP开发缓存提高网站的可扩展性
      2023-11-07

      python如何利用自带的缓存机制提高效率

      这篇文章将为大家详细讲解有关python如何利用自带的缓存机制提高效率,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。利用自带的缓存机制提高效率缓存是一种将定量数据加以保存,以备迎合后续获取需求的处理方式,
      2023-06-27

      学习正确使用pip安装Python扩展包的方法

      pip安装命令解析:学习如何正确安装Python扩展包,需要具体代码示例概述:在Python编程过程中,我们经常需要使用各种不同的扩展包来帮助我们完成各种任务。pip是Python的包管理器,它可以帮助我们快速方便地安装、卸载和管理扩展包
      学习正确使用pip安装Python扩展包的方法
      2024-01-18

      Python 使用 Redis 作为缓存的操作方法

      目录python 如何使用 Redis 作为缓存一、引言二、什么是 Redis?三、Redis 作为缓存的优势四、安装 Redis 和 Python Redis 库4.1 安装 Redis4.2 安装 Python Redis 库五、使用
      Python 使用 Redis 作为缓存的操作方法
      2024-10-11

      vue中缓存组件keepalive的介绍及使用方法

      这篇文章主要介绍了vue缓存组件keepalive的相关资料,keep-alive组件是使用includeexclude这两个属性传入组件名称来确认哪些可以被缓存的,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
      2022-11-13

      windows电脑硬盘中磁盘自动扩展和收缩的使用方法

      这期内容当中小编将会给大家带来有关windows电脑硬盘中磁盘自动扩展和收缩的使用方法,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。在我们日常使用Windows系统的过程中,可能会遇到磁盘分区的使用空间不
      2023-06-14

      Python的Flask框架使用Redis做数据缓存的配置方法

      Redis是一款依据BSD开源协议发行的高性能Key-Value存储系统。会把数据读入内存中提高存取效率。Redis性能极高能支持超过100K+每秒的读写频率,还支持通知key过期等等特性,所以及其适合做缓存。 下载安装 根据redis中文
      2022-06-04

      电脑硬盘之磁盘自动扩展和收缩的使用方法(图文教程)

      在我们日常使用Windows系统的过程中,可能会遇到磁盘分区的使用空间不足的情况,但是在Windows 7之前版本的Windows系统要想对分区进行扩展和收缩就非常的麻烦,分区小的可能需要几个小时,分区大的可能需要一天的时间。而现在wind
      2023-05-26

      编程热搜

      • Python 学习之路 - Python
        一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
        Python 学习之路 - Python
      • chatgpt的中文全称是什么
        chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
        chatgpt的中文全称是什么
      • C/C++中extern函数使用详解
      • C/C++可变参数的使用
        可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
        C/C++可变参数的使用
      • css样式文件该放在哪里
      • php中数组下标必须是连续的吗
      • Python 3 教程
        Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
        Python 3 教程
      • Python pip包管理
        一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
        Python pip包管理
      • ubuntu如何重新编译内核
      • 改善Java代码之慎用java动态编译

      目录