自定义一个cache函数,实现过期清除key的功能(5秒)
import inspect
from functools import wraps
import time
import datetime
def cache(fn):
local_cache = {} # 对不同函数名是不同的cache
@wraps(fn)
def wrapper(*args, **kwargs):
def _clear_expire():
# 清除缓存:注意:在对字典迭代的时候,是不能删除的!
expire_keys = []
# for k, v in local_cache.items(): # {(('x', 4), ('y', 5)): (9, 1535638337.355427)}
# ret, stamp = v
# 等价
for k,(_,stamp) in local_cache.items():
if datetime.datetime.now().timestamp() - stamp > 5:
expire_keys.append(k)
for k in expire_keys:
local_cache.pop(k)
# 每次都要遍历,最好用线程,用的时候清除
def _make_key(args,kwargs):
sig = inspect.signature(fn) # 获取签名 (x=4, y=5)
params = sig.parameters # 获取参数字典,有序的 OrderedDict([('x', <Parameter "x=4">), ('y', <Parameter "y=5">)])
values = list(params.values()) # 有序的 [<Parameter "x=4">, <Parameter "y=5">]
keys = list(params.keys()) # ['x', 'y']
param_dic = {} # c参数字典
# 位置传参
for k, v in enumerate(args):
param_dic[keys[k]] = v
param_dic.update(zip(params.keys(), args)) # 二元组,放到字典中,形成 k-v对
# 关键字传参
param_dic.update(kwargs) # 关键字参数,放到字典中
# 缺省值
for k, v in params.items(): # OrderedDict([('x', <Parameter "x=4">), ('y', <Parameter "y=5">)])
if k not in param_dic:
param_dic[k] = v.default
key = tuple(sorted(param_dic.items())) # sorted生成列表,不能做key,所以tuple一下(key必须是可hash的,因为要用字典) (('x', 4), ('y', 5))
return key
_clear_expire()
key = _make_key(args,kwargs)
if key not in local_cache.keys():
local_cache[key] = fn(*args, **kwargs), datetime.datetime.now().timestamp() # 放到二元组中,记录的是缓存的时间
# 形成一个 {key:stamp}的字典
#如果说到点清除,最好写结束时间,到点清除,记录一个未来时间
print(local_cache) # {(('x', 4), ('y', 5)): (9, 1535638337.355427)}
# print(local_cache[key])
return local_cache[key]
return wrapper
@cache
def add(x,y):
return x+y
add(4,5)
time.sleep(5)
add(4,y=5)
time.sleep(5)
add(x=4,y=5)