尧图精选

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

🕒 发布时间:2026/9/2 17:42:24 📁 来源:尧图网络
目录, 2. 关于.wrap装饰器产生的影响, 3. 说说自制简易的.缓存同redis缓存之间的区别, 5. 进行总结。要详细讲述缓存方法是怎样达成的, 需与官方文档以及源码相结合, 它跟redis缓存所存在的区别是什么, 在使用期间碰到.wrap装饰器时会出现怎样的改变, 还要知晓它给我们予以了哪些功能, 之后在这个基础之上实现我们自己制作的缓存方法, 本篇博客就要述及这些内容。1. 的使用1.1 参数详解下面是方法那儿的实行做出来的情况, 我们瞅见, 能够供我们传进去的参数存在两个以及typed, 倘使不进行传递的话, 那么其所具备的默认值是128, typed的默认值是False。里边的参数所代表的, 是经过装饰的方法能够缓存的最大结果数量, 要是其值为默认的128, 这就意味着被装饰的方法最多能够缓存128个返回的结果, 要是传入的值是None, 那就表明可以缓存无穷多个结果 , 你也许会好奇经过装饰的那方法的n 个结果是如何出现的 , 举个例子 , 被装饰的方法设的是def add(a, b): , 当这个函数被装饰好之后 , 我们调用add(1, 2)以及add(3 ,4) 就会缓存不一样的结果。倘若typed被设置成true , 不同类型的函数参数会被分开来缓存。比如说, f(3), 还有f(3.0), 会被当作有差异的, 然后分别进行缓存处理。def lru_cache(maxsize128, typedFalse): 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_function1.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(新增用户成功)在上面这个用法里, 我们, 要是我们将装饰器与装饰器把位置进行调换的话, 上述的那种写法将会出现报错, 这是由于装饰器之中运用了.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. .wrap装饰器对的影响于上节时我们见到, 鉴于以及.()装饰器的顺序存有差异, 故而致使程序出现是否报错的情况, 其中主要涵盖两点:当我们了解完这两点后就可以理解上述写法了。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 Get in Get in Get in Get in f是不是很像中的中间件的执行顺序其实原理都差不多。2.2 .wrap原理引用其他博主的描述装饰器在进行实现之际被装饰之后的那个函数实际上已然成为另外的一个函数了, 函数名以及等诸多函数属性会出现改变, 鉴于此为了不造成影响, 在有的包当中提供了一个被称作wraps的东西来消除如此这般的副作用, 当去写一个的时候, 最好是在实现之前添加的wrap, 它能够留存原有函数的名称以及。添加补充内容, 该函数会设置一个属性, 这个属性用来指向原函数, 目的是为了能够对原函数进行访问, 如此一来, 便能够对上文中1.3节内我们所采用的写法做出解释了。2.3 使用wrap装饰器前后的变化未完待续。。。。。。。。。3. 自制简易的3.1 提供的功能缓存装饰器提供的功能有可以知道, 从所列出的功能来讲, 自带的缓存方法能够满足我们在日常工作里的大部分需求, 如果是这样的话, 只不过它不包含一项较为重要的特性, 也就是超时自动去删除缓存结果这方面, 因此在我们自己制作的当中, 我们会去实现缓存的超时过期这项功能。3.2 cache的核心部件在作用域内存在一个相对全局的字典变量cache{}设置处于作用域之内的、相对全局而言的变量, 其中涵盖命中次数 hits, 有着未命中次数, 存在最大缓存数量, 还有当前缓存大小。第二点中的缓存信息中增加缓存加入时间和缓存有效时间3.3 的实现待实现。。。。。。。。。。。。4. 缓存和redis缓存的区别比较类型缓存类型缓存在app进程内存中缓存在redis管理的内存中分布式只缓存在单个app进程中可做分布式缓存数据类型hash 参数作为key返回结果为value有5种类型的数据结构适用场景比较小型的系统、单体应用常用的缓存解决方案功能缓存功能但是缺少过期时间控制但是使用上更加便捷具备缓存需要的各种要素5. 总结纵观上述情况, 自带的缓存功能乃应用于相对较为小型的单体应用中。其优势在于能够极为便利地依据传入各类不同参数来缓存相应结果, 而且能够切实有效地把控缓存结果数量, 当超出所设数量之际, 依据LRU算法淘汰命中次数最少的缓存结果。其不足在于没办法去设置缓存过期时间。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →