(转)实现一个cache装饰器,实现过期可清除功能

原文:http://www.cnblogs.com/JerryZao/p/9574927.html

http://blog.51cto.com/11281400/2107790-----装饰器应用练习

文件私聊下载

  灵感来自

from functools import lru_cache 的源代码,_make_key

  1 ‘‘‘ 实现一个cache 装饰器,实现可过期被清除的功能‘‘‘
  2
  3 # 第一步,实现了 与参数输入不同,也就是说,传入值后,
  4 # 不管什么样子,只要传入的顺序一样,结果一样,传入的值形成的 key 是一样的,这里用 {(‘x‘,4),(‘y‘,5)}
  5 ‘‘‘ #通过sorted排序后,新进来的key 只要排序后 与前面的不同,就是不同的key
  6 add(4,5)
  7 add(x=4,y=5)
  8 add(4,y=5)
  9 add()
 10 -------输出的key都是一样的
 11 ‘‘‘
 12 import inspect
 13 from functools import wraps
 14 import  time
 15
 16 def cache(fn):
 17
 18     @wraps(fn)
 19     def wrapper(*args, **kwargs):
 20         sig = inspect.signature(fn)
 21         params = sig.parameters
 22
 23         values = list(params.values()) # 有序的
 24         keys = list(params.keys())
 25         print(values, keys)
 26
 27         param_dic = {}
 28         #位置传参
 29         # for k, v in enumerate(args):
 30         #     param_dic[keys[k]] = v
 31         # 等价
 32         param_dic.update(zip(params.keys(), args))
 33         #关键字传参
 34         param_dic.update(kwargs)
 35         # 缺省值
 36         for k, v in params.items():
 37             if k not in param_dic:
 38                 param_dic[k] = v.default
 39         key = tuple(sorted(param_dic.items())) # sorted生成列表,不能做key,所以tuple一下
 40         print(key)
 41         return fn(*args, **kwargs)
 42     return wrapper
 43
 44 @cache
 45 def add(x=4, y=5):
 46     return  x + y
 47
 48
 49 add(4,5)
 50 time.sleep(3)
 51 add(x=4,y=5)
 52 time.sleep(3)
 53 add(4,y=5)
 54
 55
 56 # 第二步,实现缓存
 57 import inspect
 58 from functools import wraps
 59 import  time
 60
 61 def cache(fn):
 62     local_cache = {} # 对不同函数名是不同的cache
 63     @wraps(fn)
 64     def wrapper(*args, **kwargs):
 65         sig = inspect.signature(fn) # 获取签名 (x=4, y=5)
 66         params = sig.parameters # 获取参数字典,有序的 OrderedDict([(‘x‘, <Parameter "x=4">), (‘y‘, <Parameter "y=5">)])
 67
 68         values = list(params.values()) # 有序的 [<Parameter "x=4">, <Parameter "y=5">]
 69         keys = list(params.keys())#   [‘x‘, ‘y‘]
 70
 71         param_dic = {} # c参数字典
 72         #位置传参
 73         # for k, v in enumerate(args):
 74         #     param_dic[keys[k]] = v
 75         # 等价
 76         param_dic.update(zip(params.keys(), args)) # 二元组,放到字典中,形成 k-v对
 77         #关键字传参
 78         param_dic.update(kwargs) # 关键字参数,放到字典中
 79         # 缺省值
 80         for k, v in params.items(): # OrderedDict([(‘x‘, <Parameter "x=4">), (‘y‘, <Parameter "y=5">)])
 81             if k not in param_dic:
 82                 param_dic[k] = v.default
 83         key = tuple(sorted(param_dic.items())) # sorted生成列表,不能做key,所以tuple一下(key必须是可hash的,因为要用字典) ((‘x‘, 4), (‘y‘, 5))
 84         # print(key)
 85         if key not in local_cache.keys():
 86             local_cache[key] = fn(*args, **kwargs)
 87         print(local_cache[key])
 88         return local_cache[key]
 89     return wrapper
 90
 91 @cache
 92 def add(x=4, y=5):
 93     time.sleep(3)
 94     return  x + y
 95
 96 add()
 97 add(4,5)
 98 add(4,y=5)
 99
100 # 第三步实现 清除缓存
101 import inspect
102 from functools import wraps
103 import  time
104 import datetime
105
106 def cache(fn):
107     local_cache = {} # 对不同函数名是不同的cache
108     @wraps(fn)
109     def wrapper(*args, **kwargs):
110         # 清除缓存:注意:在对字典迭代的时候,是不能删除的!
111         expire_keys = []
112         # for k, v  in local_cache.items(): # {((‘x‘, 4), (‘y‘, 5)): (9, 1535638337.355427)}
113         #     ret, stamp = v
114         # 等价
115         for k,(_,stamp) in local_cache.items():
116             if datetime.datetime.now().timestamp() - stamp > 5:
117                 expire_keys.append(k)
118         for k in expire_keys:
119             local_cache.pop(k)
120         # 每次都要遍历,最好用线程,用的时候清除
121
122
123         sig = inspect.signature(fn) # 获取签名 (x=4, y=5)
124         params = sig.parameters # 获取参数字典,有序的 OrderedDict([(‘x‘, <Parameter "x=4">), (‘y‘, <Parameter "y=5">)])
125
126         values = list(params.values()) # 有序的 [<Parameter "x=4">, <Parameter "y=5">]
127         keys = list(params.keys())#   [‘x‘, ‘y‘]
128
129         param_dic = {} # c参数字典
130         #位置传参
131         # for k, v in enumerate(args):
132         #     param_dic[keys[k]] = v
133         # 等价
134         param_dic.update(zip(params.keys(), args)) # 二元组,放到字典中,形成 k-v对
135         #关键字传参
136         param_dic.update(kwargs) # 关键字参数,放到字典中
137         # 缺省值
138         for k, v in params.items(): # OrderedDict([(‘x‘, <Parameter "x=4">), (‘y‘, <Parameter "y=5">)])
139             if k not in param_dic:
140                 param_dic[k] = v.default
141         key = tuple(sorted(param_dic.items())) # sorted生成列表,不能做key,所以tuple一下(key必须是可hash的,因为要用字典) ((‘x‘, 4), (‘y‘, 5))
142         # print(key)
143         if key not in local_cache.keys():
144             local_cache[key] = fn(*args, **kwargs), datetime.datetime.now().timestamp() # 放到二元组中,记录的是缓存的时间
145             # 形成一个 {key:stamp}的字典
146             #如果说到点清除,最好写结束时间,到点清除,记录一个未来时间
147
148         print(local_cache) # {((‘x‘, 4), (‘y‘, 5)): (9, 1535638337.355427)}
149         print(local_cache[key])
150         return local_cache[key]
151     return wrapper
152
153 @cache
154 def add(x=4, y=5):
155     time.sleep(3)
156     return  x + y
157
158 add()
159 add(4,5)
160 add(4,y=5)
161
162 # 第五步 优化:
163 import inspect
164 from functools import wraps
165 import  time
166 import datetime
167
168 def logger(): #时间装饰器
169     pass
170
171 def cache(fn):
172     local_cache = {} # 对不同函数名是不同的cache
173     @wraps(fn)
174     def wrapper(*args, **kwargs):
175         def _clear_expire():
176             ‘‘‘ 优化1‘‘‘
177             # 清除缓存:注意:在对字典迭代的时候,是不能删除的!
178             expire_keys = []
179             # for k, v  in local_cache.items(): # {((‘x‘, 4), (‘y‘, 5)): (9, 1535638337.355427)}
180             #     ret, stamp = v
181             # 等价
182             for k,(_,stamp) in local_cache.items():
183                 if datetime.datetime.now().timestamp() - stamp > 5:
184                     expire_keys.append(k)
185             for k in expire_keys:
186                 local_cache.pop(k)
187             # 每次都要遍历,最好用线程,用的时候清除
188         def _make_key(args,kwargs):
189             sig = inspect.signature(fn)  # 获取签名 (x=4, y=5)
190             params = sig.parameters  # 获取参数字典,有序的 OrderedDict([(‘x‘, <Parameter "x=4">), (‘y‘, <Parameter "y=5">)])
191             values = list(params.values())  # 有序的 [<Parameter "x=4">, <Parameter "y=5">]
192             keys = list(params.keys())  # [‘x‘, ‘y‘]
193             param_dic = {}  # c参数字典
194             # 位置传参
195             # for k, v in enumerate(args):
196             #     param_dic[keys[k]] = v
197             # 等价
198             param_dic.update(zip(params.keys(), args))  # 二元组,放到字典中,形成 k-v对
199             # 关键字传参
200             param_dic.update(kwargs)  # 关键字参数,放到字典中
201             # 缺省值
202             for k, v in params.items():  # OrderedDict([(‘x‘, <Parameter "x=4">), (‘y‘, <Parameter "y=5">)])
203                 if k not in param_dic:
204                     param_dic[k] = v.default
205             key = tuple(sorted(param_dic.items()))  # sorted生成列表,不能做key,所以tuple一下(key必须是可hash的,因为要用字典) ((‘x‘, 4), (‘y‘, 5))
206             # print(key)
207             return key
208
209         _clear_expire()
210
211         key = _make_key(args,kwargs)
212
213         if key not in local_cache.keys():
214             local_cache[key] = fn(*args, **kwargs), datetime.datetime.now().timestamp() # 放到二元组中,记录的是缓存的时间
215             # 形成一个 {key:stamp}的字典
216             #如果说到点清除,最好写结束时间,到点清除,记录一个未来时间
217
218         print(local_cache) # {((‘x‘, 4), (‘y‘, 5)): (9, 1535638337.355427)}
219         print(local_cache[key])
220         return local_cache[key]
221
222     return wrapper
223
224
225 # 多装饰器,从下往上执行
226 @logger
227 @cache
228 def add(x=4, y=5):
229     time.sleep(3)
230     return  x + y
231
232 add()
233 add(4,5)
234 add(4,y=5)

原文地址:https://www.cnblogs.com/liujiacai/p/9844948.html

时间: 2024-08-02 22:11:24

(转)实现一个cache装饰器,实现过期可清除功能的相关文章

一个图片装饰器的制作

一个图片装饰器的制作一1 首先创建工程picDecor,2 然后从对象库中,拉出Round Rect按钮到视图中,3 为了显示用户所选择的图片,需要往视图里, 添加view Controller对象,如下图4 还要一个图片视图imageView来编辑一张图片和一个windows and Bars工具栏来放置按钮,(备注:要先添加工具栏再添加iamgeView对像)5 再添加flexible space bar Button Item到工具栏中心,然后再添加一个bar buttonItem到工具栏

一个函数装饰器

Python的函数是对象 Python  函数可以被赋值def  hello():–print('hello!') a = hello       #注: 此处没有() ,是一个对象 a()        # 调用a() 结果与hello() 相同 此时删除 hello,a() 依然保持原属性 函数可以定义在另一个函数里面 def say(): def hello(): return 'hello' return hello 外层的say函数会把内层的 hello函数的执行结果输出 函数可以返回

实现一个Porperty装饰器,可以把方法装饰成同一个属性名

今天简单的实现下Porperty装饰器demo: class Porperty: def __init__(self, fget= None, fset= None, fdel = None): self.fget= fget self.fset = fset self.fdel = fdel def __get__(self, instance, cls): if instance is None: return self if not callable(self.fget): raise A

Python装饰器实现类Java注解功能

最近想用Python写一个简单生成器,类似指定类型和范围,返回指定列表: 比如想要  0 ~ 3 的整数,则 我只需要指定: 最小:0, 最大:3, 步长:1 则返回一个 [0,1,2,3] 的列表 思路是用Python 装饰器,在def方法上打装饰器,装饰器内部替换方法调用时传入的参数值 代码如下: 1 # coding=utf-8 2 3 def integer(min=0, max=100, step=1): 4 def deco(func): 5 def wrapper(val): 6

实现一个重试装饰器

class retry(object): """A retry decorator.""" def __init__(self, exception=Exception, timeout=None, retries=None, interval=0.001, logfun=lambda s: print(s, file=sys.stderr), ): if timeout and retries: raise ValueError("t

functools模块(partial,lru_cache装饰器)

partial方法 偏函数,把函数部分的参数固定下来,相当于为部分的参数添加了一个固定的默认值,形成一个新的函数并返回.从partial生成的新函数,是对原函数的封装. import functools def add(x, y) -> int: return x + y newadd = functools.partial(add, y=5) print(newadd(7)) print(newadd(7, y=6)) print(newadd(y=10, x=6)) import inspe

装饰器器应用及用途

装饰器的应用 一:实现一个cache装饰器,实现可过期被清除的功能 简化设计,函数的形参定义不包含可变位置参数.可变关键字参数和keyword_only参数, 可以不考虑缓存满了之后的换出问题. 数据类型的选择 缓存的应用场景,是有数据需要频繁查询,且每次查询都需要大量计算或者等待时间之后才能返回结果的情况,使用缓存来提高查询速度,用空间换时间. cache应该选用什么数据结构? 便于查询的,且能快速好到数据的数据结构. 每次查询的时候,只要输入一致,就应该得到同样的结果(顺序也一致,例如减法函

python3.5.2之装饰器(1)

一.本次实验环境: 在腾讯云虚拟主机centos7上配置pyenv多版本python管理器,并安装交互式web编辑器jupyter,python版本为3.5.2.  二.装饰器: 装饰器的本质是一个函数,接收一个函数作为参数,并且返回一个函数 带参数的装饰器是一个函数,返回一个装饰器 带参数的装饰器最多允许一层,timeit()()(不允许) 在python中,一个函数可以作为参数传递给另外一个函数,还可返回一个函数(不了解此请看高阶函数)因此,我们可以把一个函数传递给另一个函数后,在这个被传递

【转】详解Python的装饰器

原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def say_hello(): print "hello!" def say_goodbye(): print "hello!" # bug here if __name__ == '__main__':