题目:
实现一个cache装饰器,实现可过期,可清除的功能,可以不换出(模仿lru_cache)
-
思路:
-
cache缓存装饰器,是有key值的---------->可得到用字典类型
-
过期指的是key值过期,过期是一定时间,可以用时间戳来做对比
-
最重要的是key值的生成,且key一定是可hash的,key可以接受位置参数,关键字参数,缺省参数
-
而位置参数解构之后是tuple
-
关键字参数解构得到dict类型,而字典是无序的。传参的顺序不一定是字典中保存的顺序
-
故而得到key之后要排序下。
-
-
-
1.先把基础功能写下来
-
先把装饰器结构写出来
-
def pr_cache(fn):
def warpper(*args,**kwargs):
ret = fn(*args,**kwargs)
return ret
return warpper -
先写key的构造
-
inspect模块的signature函数,可以获取函数的所有参数
-
default
-
获得函数的关键字参数的值
-
import inspect import functools def pr_cache(fn): @wraps(fn) def warpper(*args,**kwargs): dict_key = {} od = inspect.signature(fn) ####有序字典 od_dict = od.parameters od_list = list(od_dict.keys()) ####位置参数 for i, v in enumerate(args): k = od_list[i] dict_key[k] = v ####关键字参数 dict_key.update(kwargs) ####缺省参数 for k in od_dict.keys(): if k not in dict_key.keys(): dict_key[k] = od_dict[k].default key = tuple(sorted(dict_key.items())) if key not in dict_key.keys(): ret = fn(*args, **kwargs) dict_key[key] = ret return dict_key[key] return warpper
-
-
- 超时的设置:代码如下
-
import inspect import functools import datetime def pr_cache(fn): dict_cache = {} def warpper(*args,**kwargs): ts_list = [] for i, (_,ts) in dict_cache.items(): if datetime.datetime.now().timestamp() - ts > 5: ts_list.append(i) for k in ts_list: dict_cache.pop(k) dict_key = {} od = inspect.signature(fn) ####有序字典 od_dict = od.parameters od_list = list(od_dict.keys()) ####位置参数 for i, v in enumerate(args): k = od_list[i] dict_key[k] = v ####关键字参数 dict_key.update(kwargs) ####缺省参数 for k in od_dict.keys(): if k not in dict_key.keys(): dict_key[k] = od_dict[k].default key = tuple(sorted(dict_key.items())) if key not in dict_cache.keys(): ret = fn(*args, **kwargs) dict_cache[key] = (ret, datetime.datetime.now().timestamp()) return dict_cache[key] return warpper @pr_cache def add(x,y=5): ret = x + y time.sleep(5) print(ret) return ret print(add(4,5)) #print(add(4)) time.sleep(5) print(add(4,y=5)) print(add(x=4,y=5)) print(add(y=5,x=4))函数的功能做出来了,测试没问题
-
但是代码还可以在整理,封装下
-
不会为了复用,而是整洁,结构化
-
-
代码如下
import inspect import functools import datetime def o_cache(overtime): def pr_cache(fn): dict_cache = {} def warpper(*args,**kwargs): def over_time(over_cache): ts_list = [] for i, (_,ts) in over_cache.items(): if datetime.datetime.now().timestamp() - ts > overtime: ts_list.append(i) for k in ts_list: over_cache.pop(k) over_time(dict_cache) def make_key(fn): dict_key = {} od = inspect.signature(fn) ####有序字典 od_dict = od.parameters od_list = list(od_dict.keys()) ####位置参数 for i, v in enumerate(args): k = od_list[i] dict_key[k] = v ####关键字参数 dict_key.update(kwargs) ####缺省参数 for k in od_dict.keys(): if k not in dict_key.keys(): dict_key[k] = od_dict[k].default return tuple(sorted(dict_key.items())) key = make_key(fn) if key not in dict_cache.keys(): ret = fn(*args, **kwargs) dict_cache[key] = (ret, datetime.datetime.now().timestamp()) return dict_cache[key] return warpper return pr_cache @o_cache(5) def add(x,y=5): ret = x + y time.sleep(3) print(ret) return ret print(add(4,5)) print(add(4)) time.sleep(5) print(add(4,y=5)) print(add(x=4,y=5)) print(add(y=5,x=4))
本文介绍如何实现一个具备过期和清除功能的缓存装饰器,模仿Python的`lru_cache`。装饰器使用字典存储缓存,通过时间戳判断过期,并确保生成的key为可哈希。关键在于正确处理位置参数、关键字参数和缺省参数,构造排序后的key。首先完成基础功能,然后利用`inspect`模块获取函数参数,设置超时,并进行代码优化,追求结构化和整洁。

2万+

被折叠的 条评论
为什么被折叠?



