python中缓存模块的一些用法
时间块间留出一些缓冲时间应对意外情况 #生活常识# #时间管理建议# #时间块管理#
python缓存模块的一些用法
一.问题描述有时候可能需要缓存一些 成员方法的值, 可能成员方法的计算比较耗时,有时候不希望重复调用计算该值, 这个时候就可以缓存该值.
查了一下标准库 有 functools.lru_cache 有一个 lru_cache 可以缓存成员函数的值,
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- """ @author: Frank @contact: frank.chang@shoufuyou.com @file: test_lru_cache.py @time: 2018/9/8 下午8:55 """ import time from functools import lru_cache class Model: @lru_cache(maxsize=10) def calculate(self, number): print(f'calculate({number}) is running,', end=' ') print('sleep 3s ') time.sleep(3) return number * 3 if __name__ == '__main__': model = Model() for i in range(5): print(model.calculate(i)) for i in range(5): print(model.calculate(i))
1234567891011121314151617181920212223242526272829303132333435结果如下:
calculate(0) is running, sleep 3s 0 calculate(1) is running, sleep 3s 3 calculate(2) is running, sleep 3s 6 calculate(3) is running, sleep 3s 9 calculate(4) is running, sleep 3s 12 0 3 6 9 12
1234567891011121314151617从结果开出来, 第二次计算的时候 , 就没有计算 而是通过缓存取值, 所以成员方法只计算了一次.
lru_cache 可以指定 max_size 缓存的大小, typed bool 如果为True, 代表不同类型分别缓存. 如果达到max_size 淘汰策略是LRU, LRU是Least Recently Used的缩写,即最近最少使用,常用于页面置换算法.
第三方的模块cachetools 已经提供了很多缓存策略,直接拿来用一下.
来看下面的例子.
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- """ @author: Frank @contact: frank.chang@shoufuyou.com @file: test_cache.py @time: 2018/9/8 下午12:59 pip install cachetools https://docs.python.org/3/library/operator.html 缓存成员方法的值 cachetools 已经实现好了, 直接用就可以了. """ from operator import attrgetter import time from cachetools import LRUCache,RRCache , cachedmethod class Model: def __init__(self, cachesize): self.cache = LRUCache(maxsize=cachesize) @cachedmethod(attrgetter('cache')) def get_double_num(self, num): """ return 2* num""" print(f'get_double_num({num}) is running') time.sleep(2) return num * 2 model = Model(cachesize=10) print(model.get_double_num(10)) print(model.get_double_num(10)) print(model.get_double_num(10)) print(model.get_double_num(10)) print(model.get_double_num(10)) print(model.get_double_num(10))
123456789101112131415161718192021222324252627282930313233343536373839404142434445结果如下:
get_double_num(10) is running 20 20 20 20 20 20 Process finished with exit code 0123456789
可以看出, 值计算一次 函数,第二次走的是缓存. 非常好用. 在初始化方法里面构造一个缓存对象, 之后用 cachedmethod 修饰成员函数,同时 用attrgetter(‘cache’) 把cache 拿到就可以用了.
实际上 cachetools 实现了很多缓存策略,具体缓存策略可以参考下面的链接.
'Cache', 'LFUCache', 'LRUCache', 'RRCache', 'TTLCache', 1234
‘cached’, ‘cachedmethod’ 这两个分别用来修饰 函数和成员方法的.
2 来看一个 缓存函数# 缓存 函数的值 from cachetools import cached @cached(cache={}) def fib(n): print((f'fib({n}) is running.')) return n if n < 2 else fib(n - 1) + fib(n - 2) for i in range(20): print('fib(%d) = %d' % (i, fib(i))) 12345678910111213
@cached(cache={}) def fun(n): print(f'fun({n}) is runnnig.') time.sleep(3) return n ** 2 if __name__ == '__main__': for _ in range(5): print(fun(4)) 1234567891011
如果cache = None , 表示不缓存,该计算结果.
结果如下:
fun(4) is runnnig. 16 16 16 16 16 1234567
直接导入 cached 里面 传入一个字典就可以了,用起来也比较方便.
实现分析:
缓存思路大致是一样的, 首先先把参数hash 一下生成一个key, 然后看key 是否在自己的缓存里,不在就计算方法(函数),之后把key和对应value 放到自己的子弟那里面. 如果下一次计算该值,生成一个key 看是否在 自己的字典里面,如果在直接返回即可. 当然这是基本的思路, 里面还有用到 缓存淘汰策略, 多线程是否要加锁,等比较复杂的问题.
三参考文档:1.http://ningning.today/2016/01/31/python/python%E7%BC%93%E5%AD%98%E7%9A%84%E4%B8%80%E4%BA%9B%E7%94%A8%E6%B3%95/
2.gitHub地址 cachetools
https://github.com/tkem/cachetools
3.cache tools 的文档
https://cachetools.readthedocs.io/en/latest/
4.https://cachetools.readthedocs.io/en/latest/#module-cachetools.func
4.缓存算法
https://en.wikipedia.org/wiki/Cache_replacement_policies
5.缓存算法(页面置换算法)-FIFO、LFU、LRU https://www.cnblogs.com/dolphin0520/p/3749259.html
分享快乐,留住感动.2018-09-08 21:34:51 –frank
网址:python中缓存模块的一些用法 https://www.yuejiaxmz.com/news/view/110380
相关内容
python serial模块的使用Python Base64模块的使用
Python中if
Python笔记——Python中is和==的区别
如何简单地理解Python中的if
【计算机视觉】基于Python—OpenCV的手势识别详解(一)
python
用Python发送邮件,需要这样三步
从初级到高级,5个可以用到生活中的Python自动化项目
基于python的膳食健康推荐系统