wrap 缓存。。。
from functools import wraps import inspect import datetime def cache(exp=0): #超时0 也就是没有超时时间 def _cache(fn): c = {} #把结果存放到cache里面,用来存储我们的缓存 @wraps(fn) def wrap(*args,**kwargs): #1 key 如何封装args kwargs print (args) print (kwargs) key=[ ] #初始化是空值 names=set() #name 需要加入,args 和kwargs的name 要做修改,names 作为key避免重复用set() params = inspect.signature(fn).parameters #获取所有的参数,获取后第一步,参数列表 #args 操作 for i ,arg in enumerate(args): #args是元祖 arg 是value,那么name是什么?args 是位置参数 #value 和params 取出的值是一样的。 args 是位置参数,所以他的顺序和params 顺序是一致的 name = list(params.keys())[i]#获取所有的key 通过下标i去访问,返回x或y # ,name是我们的key key.append((name,arg)) #把元祖丢进去 key====>[(x,1),(y,2)] names.add(name) #把上面的name丢进去 #kwargs操作 #for k,v in kwargs.items(): # key.append((k,v)) #更简单办法 key.extend(kwargs.items()) #key 已经封装了 names.update(kwargs.keys()) #kwargs的names更新了 for k,v in params.items(): #之前的params的list params是整个函数的参数列表 #如何获取默认参数, #***如果定义函数的时候,有默认参数,在传参的时候没有传这个默认参数,我们就拿不到它 #params是整个函数的参数列表 #判断params里不在names里的 就是默认参数 if k not in names: key.append((k,v.default)) #排序 key是列表,列表有个方法key.sort、 sort参数有个key用于传fan,x就是指key里面每个迭代对象 #x 可能是[(x,1),(y,2)]里面的(x,1) 或 (y,2)元祖,按照每个列表里面每一个元素的第一个排序,也就是key排序 key.sort(key=lambda x:x[0]) #key 排序后进行封装,用& join 列表解释式做 key = '&'.join([ f'{name}={arg}'for name,arg in key]) #for name,args in key j解构 print (key) #命中监测 if key in c.keys(): # 超时监测 #如何判断一组key 什么时候执行过呢 #key &ts=2222233,还有一种, #key=(key,timestamp):values 用这个 用参数解构 ret,timestamp =c[key] #拿到结果里面 有timestap 接收 if exp==0 or datetime.datetime.now().timestamp() - timestamp< exp: #满足命中缓存的添加的输出结果 print(f'命中缓存:{key}:{args},{kwargs}') return c[key] #2 超时监测 #最后拿到结果 ret = fn(*args,**kwargs) ret = fn(*args,**kwargs) print('缓存未命中') c[key] = (ret,datetime.datetime.now().timestamp()) #元祖 return ret return wrap return _cache