python 函数结果缓存一段时间的装饰器
把函数结果缓存一段时间,比如读取一个mongodb,mongodb中的内容又在发生变化,如果从部署后,自始至终只去读一次那就感触不到变化了,如果每次调用一个函数就去读取那太频繁了耽误响应时间也加大了cpu负担,也不行。那就把结果缓存一段时间。
来一个缓存一段时间的装饰器。
class FunctionResultCacher:
logger = LogManager('FunctionResultChche').get_logger_and_add_handlers()
func_result_dict = {}
"""
{
(f1,(1,2,3,4)):(10,1532066199.739),
(f2,(5,6,7,8)):(26,1532066211.645),
}
""" @classmethod
def cached_function_result_for_a_time(cls, cache_time):
"""
函数的结果缓存一段时间装饰器
:param cache_time 缓存的时间
:type cache_time : float
""" def _cached_function_result_for_a_time(fun): @wraps(fun)
def __cached_function_result_for_a_time(*args, **kwargs):
if len(cls.func_result_dict) > 1024:
cls.func_result_dict.clear() key = cls._make_arguments_to_key(args, kwargs)
if (fun, key) in cls.func_result_dict and time.time() - cls.func_result_dict[(fun, key)][1] < cache_time:
return cls.func_result_dict[(fun, key)][0]
else:
result = fun(*args, **kwargs)
cls.func_result_dict[(fun, key)] = (result, time.time())
cls.logger.debug('函数 [{}] 此次不使用缓存'.format(fun.__name__))
return result return __cached_function_result_for_a_time return _cached_function_result_for_a_time @staticmethod
def _make_arguments_to_key(args, kwds):
key = args
if kwds:
sorted_items = sorted(kwds.items())
for item in sorted_items:
key += item
return key
测试下:
@FunctionResultCacher.cached_function_result_for_a_time(3)
def f10(a, b, c=3, d=4):
print('计算中。。。')
return a + b + c + d print(f10(1, 2, 3, 4))
print(f10(1, 2, 3, 4))
time.sleep(4)
print(f10(1, 2, 3, 4)) 运行结果是这样
可以发现只计算了两次,第一次是开始时候没有缓存所以要计算,第二次有缓存了就不计算,第三次因为超过了3秒就不使用缓存了,所以要计算。
需要注意一点的是用字典做的缓存,如果函数的结果非常大,部署后一直运行,一段时间后会占一大块内存,所以设置了1024个缓存结果,否则就清除字典。如果函数没有入参或者入参都是一样的那就没事,如果入参不一样且函数返回结果超长是一个几百万长度的字符串,那就用此装饰器时候要小心点。
把if len(cls.func_result_dict) > 1024: 改为if sys.getsizeof(cls.func_result_dict) > 100 * 1000 * 1000,则是直接判断内存。
此装饰器可以装饰在函数上,当然也可以装饰在方法上了。因为 *args **kwargs代表了所有参数,self只是其中的一个特殊参数而已,所以可以装饰在方法上。 functools模块有个lru_cache装饰器,是缓存指定次数的装饰器,这个是缓存指定时间的。
python 函数结果缓存一段时间的装饰器的更多相关文章
- 12、Python函数高级(命名空间、作用域、装饰器)
一.名称空间和作用域 1.命名空间(Namespace) 命名空间是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的. 命名空间提供了在项目中避免名字冲突的一种方法.各个命名空 ...
- Python函数名做参数,闭包,装饰器
简单讲解闭包的写法和应用,在这之前,先声明,你定义的任意一个函数都可以作为其他函数的参数.就像下面这段代码的参数func,接收的参数就是一个函数名,在函数体内部使用了func()调用执行函数. 请看下 ...
- python 全栈开发,Day12(函数的有用信息,带参数的装饰器,多个装饰器装饰一个函数)
函数的执行时,*打散.函数的定义时,*聚合. from functools import wraps def wrapper(f): # f = func1 @wraps(f) def inner(* ...
- Python学习(三):迭代器、生成器、装饰器、递归、算法、正则
1.迭代器 迭代器是访问集合的一种方式,迭代对象从集合的第一个元素开始访问,直到元素被访问结束,迭代器只能往前不能后退,最大的优点是不要求事先准备好整个迭代过程中的元素,这个特点使得它特别适合用于遍历 ...
- Python自动化面试必备 之 你真明白装饰器么?
Python自动化面试必备 之 你真明白装饰器么? 装饰器是程序开发中经常会用到的一个功能,用好了装饰器,开发效率如虎添翼,所以这也是Python面试中必问的问题,但对于好多小白来讲,这个功能 有点绕 ...
- Python 第四篇:生成器、迭代器、装饰器、递归函数与正则表达式
一:生成器:Generator,可以理解为是一种一个函数产生一个迭代器,而迭代器里面的数据是可以通过for循环获取的,那么这个函数就是一个生成器,即生成器是有函数生成的,创建生成器使用()表示,比如g ...
- python中“生成器”、“迭代器”、“闭包”、“装饰器”的深入理解
python中"生成器"."迭代器"."闭包"."装饰器"的深入理解 一.生成器 1.生成器定义:在python中,一边 ...
- python语法生成器、迭代器、闭包、装饰器总结
1.生成器 生成器的创建方法: (1)通过列表生成式创建 可以通过将列表生成式的[]改成() eg: # 列表生成式 L = [ x*2 for x in range(5)] # L = [0, 2, ...
- Python开发【第十四篇】装饰器
装饰器 什么是装饰器? 装饰器是一个函数,主要作用是用来给包装另一个函数或者类 包装的目的是不改变原函数名(或类名)的情况下改变或添加被包装对象的功能 函数装饰器 是指装饰器是一个函数,传入的是一 ...
随机推荐
- Linux排序命令sort详解
语法格式sort [ -A ] [ -b ] [ -c ] [ -d ] [ -f ] [ -i ] [ -m] [ -n ] [ -r ] [ -u ] [ -o OutFile ][ -t Cha ...
- Android SDK Manager速度慢
转载自:http://www.cnblogs.com/tc310/archive/2012/12/21/2828450.html Android SDK Manager 无法下载更新,或者更新速度超慢 ...
- Python基础知识小结
1. 关于函数传参 def func(n, *args, **kwargs): print n print args print kwargs if __name__ == '__main__': # ...
- log4写完日志不会自动释放
今天想做个日志记录功能.网上查了下.决定使用log4net 来做. 但是最发现在写日志的时候.会一直占用当前的日志文件.当你想查看的时候会提示另一个进程占用了该文件. 只有到他创建下一个日志文件.然后 ...
- SpringBoot的文件下载
SpringBoot的文件下载 2017年11月29日 10:32:20 阅读数:3907 SpringBoot的文件下载方法有很多,此处只记录使用Spring的Resource实现类FileSyst ...
- mybatis动态sql中的两个内置参数(_parameter和_databaseId)
mybatis动态sql中的两个内置参数(_parameter和_databaseId) <!-- mybatis动态sql的两个内置参数 不只是方法传递过来的参数可以被 ...
- 递归 - 求 n 个球中取 m 个不同的球,有多少种取法?
代码: #include <iostream> using namespace std; int F(int _n, int _m) { if(_n < _m) return 0; ...
- CREATESTRUCT cs 结构体
PreCreateWindow(CREATESTRUCT& cs) typedef struct tagCREATESTRUCT { LPVOID lpCreateParams; // 创建窗 ...
- socket阻塞与非阻塞,同步与异步、I/O模型
socket阻塞与非阻塞,同步与异步 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:同步: 所 ...
- mysql深坑之--group_concat有长度限制!!!!默认1024
在mysql中,有个函数叫“group_concat”,平常使用可能发现不了问题,在处理大数据的时候,会发现内容被截取了,其实MYSQL内部对这个是有设置的,默认不设置的长度是1024,如果我们需要更 ...
