使用装饰器模拟实现FIFO缓存
在学习python过程中找到一个非常不错的网站,看到博主讲解装饰器的时候给出了模拟FIFO缓存的代码,但是代码中有一些缺陷,本文在学习该博主的代码的基础上,修补了代码中的缺陷。
博主原代码:
from functools import wraps
from inspect import signature
def fifo_cache(maxsize=128):
lst = []
cache = {}
def wrapper(func):
sig = signature(func)
@wraps(func)
def inner(*args,**kwargs):
bond_values = sig.bind(*args,**kwargs)
key = bond_values.__str__()
value = cache.get(key)
if value is not None:
res = "hit the cache:" + str(value)
return res
if len(lst) >= maxsize:
oldkey = lst.pop(0)
if oldkey in cache:
cache.pop(oldkey)
result = func(*args,**kwargs)
lst.append(key)
cache[key] = result
return result
return inner
return wrapper
@fifo_cache()
def test1(x, y):
return x + y
@fifo_cache()
def test2(x, y, z=20):
return x + y + z
print(test1(19, 20))
print(test1(19, 20))
print(test1(20, 19))
print(test2(19, 20, 20))
print(test2(19, 20))
运行结果:
[root@code-server-lzj vscode-lzj]
39
hit the cache:39
39
59
59
缺陷:
1、函数test2的最后一个参数z是默认参数,默认值是20, test2(19, 20, 20) 与 test2(19, 20) 本质上传入的参数是相同的,但在inner函数里接收到的参数里没有默认参数的数值,无法命中缓存。
2、当参数值互换位置时,实际上是同一情况,如test1(19,20) test1(20,19)无法命中缓存。
改进之后的代码:
from functools import wraps
from inspect import signature
def fifo_cache(maxsize=128):
lst = []
cache = {}
def wrapper(func):
sig = signature(func)
@wraps(func)
def inner(*args):
bound_args = sig.bind(*args)
bound_args.apply_defaults()
target_args = dict(bound_args.arguments)
key = []
for v in target_args.values():
key.append(v)
key.sort()
key = str(key)
value = cache.get(key)
if value is not None:
res = "hit the cache:" + str(value)
return res
if len(lst) >= maxsize:
oldkey = lst.pop(0)
if oldkey in cache:
cache.pop(oldkey)
result = func(*args)
lst.append(key)
cache[key] = result
return result
return inner
return wrapper
@fifo_cache()
def test1(x, y):
return x + y
@fifo_cache()
def test2(x, y, z=20):
return x + y + z
print(test1(19, 20))
print(test1(20, 19))
print(test1(1,1))
print(test2(19, 20, 20))
print(test2(19, 20))
print(test2(20, 19))
print(test2(20,20,19))
print(test2(20,2,19))
运行结果:
[root@code-server-lzj vscode-lzj]
39
hit the cache:39
2
59
hit the cache:59
hit the cache:59
hit the cache:59
41
改进后的代码成功地解决了上述的两个缺陷。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)