数据的每次获取通常都需要大量的计算或者等待(浪费)大量的时间。
对于某些经常被使用的数据来说,缓存的存在就至关重要了。
数据类型的选择
为了使数据更便捷有效的提取出来,只要输入的数据一致,计算得出的结果也一样,无疑,字典是最好的选择,以输入的参数为key,输出的函数返回值为value。
key的使用
需要注意的问题就是key的存储,key必然为hashable,位置参数是存储在元组中,元组是有序的不做考虑,然而,字典是无序的(虽然3.6以后会记录key的插入顺序,然并卵,某些解释器没有这个功能),第一个想法就是OrderedDict,或许,我们有别的方法来实现。
参数遇到的问题
还有一个问题就是传参的时候,位置传参和关键字传参的混合使用,或者是同样的数据不同的传参方式,若要实现同样的数据参数输入他们全部的输出值都一样,或者说一个输出值的实现,就要使用inspect来实现。
算法思路与实现过程
inspect模块获取的是一个函数签名,取parameters后,这就会是一个有序字典(间接的使用了OrdereDict),保存我们输入的参数信息。
虽然普通的函数调用也可以,但是我想让我的代码高端一些,说起高端,自然是向源码看齐,我们可以用一下lru_cache的模板来构建函数,使使用者使用函数的时候不太容易察觉使用了缓存。
模板如下:
from functools import wraps
import inspect
def mag_cache(fn):
local_cache = {
} # 对不同函数名是不同的cache
@wraps(fn)
def wrapper(*args,**kwargs): #接收各种参数
# 参数处理,构建key
ret = fn(*args,**kwargs)
return ret
return wrapper
@mag_cacahe
def add(x, y , z=6):
return x + y + z
完成了key的生成:本次使用了普通的字典params_dict,先把位置参数的对应好,再填充关键字参数,最后补充缺省值,然后再排序生成key。
代码如下
from functools import wraps
import inspect
def mag_cache(fn):
local_cache = {
} # 对不同函数名是不同的cache
@wraps(fn)
def wrapper(*args, **kwargs):
# 参数处理,构建key
sig = inspect.signature(fn)
params = sig.parameters # 只读有序字典
param_names = [key for key in params.keys()] # list(params.keys())
target