原文: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)
为什么要坚持,想一想当初!

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

  1. 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...

  2. python 装饰器 (多个装饰器装饰一个函数---装饰器前套一个函数)

    #带参数的装饰器 #500个函数 # import time # FLAGE = False # def timmer_out(flag): # def timmer(func): # def inn ...

  3. Python装饰器实现几类验证功能做法(续)

    :昨天聊了一下构造.今天试了一下.感觉昨天聊的还是不够细化.今天结合代码实现,加以一点补充. 首先观察下面这个例子 from functools import wrapsdef decorator(f ...

  4. Python装饰器实现几类验证功能做法

    最近新需求来了,要给系统增加几个资源权限.尽量减少代码的改动和程序的复杂程度.所以还是使用装饰器比较科学 之前用了一些登录验证的现成装饰器模块.然后仿写一些用户管理部分的权限装饰器.比如下面这种 de ...

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

    最近想用Python写一个简单生成器,类似指定类型和范围,返回指定列表: 比如想要  0 ~ 3 的整数,则 我只需要指定: 最小:0, 最大:3, 步长:1 则返回一个 [0,1,2,3] 的列表 ...

  6. 装饰器实现session登陆 验证功能

    装饰器 登陆验证功能 1.装饰器模板 from django.shortcuts import render, redirect, HttpResponse from django.conf impo ...

  7. python 装饰器 第二步:扩展函数的功能(不修改原函数)

    # 第二步:扩展函数的功能(不能修改原函数) # 用于扩展基本函数的函数 # 把一个函数(eat函数)作为一个整体传给另外一个函数(kuozhan函数) # 这个函数(kuozhan函数)用形参fun ...

  8. Python入门篇-装饰器

    Python入门篇-装饰器 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.装饰器概述 装饰器(无参) 它是一个函数 函数作为它的形参 返回值也是一个函数 可以使用@functi ...

  9. [原创]django+ldap实现单点登录(装饰器和缓存)

    前言 参考本系列之前的文章,我们已经搭建了ldap并且可以通过django来操作ldap了,剩下的就是下游系统的接入了,现在的应用场景,我是分了2个层次,第一层次是统一认证,保证各个系统通过ldap来 ...

随机推荐

  1. 【repost】Chrome 控制台console的用法

    下面我们来看看console里面具体提供了哪些方法可以供我们平时调试时使用. 目前控制台方法和属性有: ["$$", "$x", "dir" ...

  2. 20155326 2016-2017-2《Java程序设计》课程总结

    20155326 2016-2017-2<Java程序设计>课程总结 (按顺序)每周作业链接汇总 20155326刘美岑的第一次作业:第一次写博客,写下了对java的期待 20155326 ...

  3. java中大数的一些基本运算

    import java.math.BigInteger; import java.util.Scanner; public class Main { public static void main(S ...

  4. 最短路 模板 【bellman-ford,dijkstra,floyd-warshall】

    Bellman-ford: /* bellman ford */ #include <iostream> #include <cstdio> #include <cstr ...

  5. 关于java弱引用

    最近在学java虚拟机相关的东西,看了一篇微信的推送  在此分享https://mp.weixin.qq.com/s/oLhZWWWIVc90cNUBukkqHw 一.强引用 强引用就是我们经常使用的 ...

  6. Android之TextView灵活使用

    Android之TextView灵活使用 在项目中有无遇到过这样一种程况,例如文字"王明今年10岁了", 但是数字10是从网络返回的数据, 而你又想把这个文字写在xml中, 过往我 ...

  7. SQL语句 删除表user 中字段name 内容重复的记录,

    public class T01 { public static void main(String[] args) { int j=4; j=j+=j-=j*=j; System.out.printl ...

  8. 分形之花篮(Flower Basket)

    这一篇展示的图形与上一篇文章分形之皇冠(Crown)很相似. 核心代码: static void FractalFlowerBasket(const Vector3& vStart, cons ...

  9. [ASE][Daily Scrum]11.06

    我们的<坦克大战·无尽>正式开始动工了,今天的任务计划如下~ [Plan] View Shilin Liu 搭建好开发环境 收集素材         Control Jiafan Zhu ...

  10. php gettext

      安装gettext: ubuntu: apt-get install php-gettext, apt-get install gettext window:开启扩展 修改locale :$ /u ...