Python 如何手动编写一个自己的LRU缓存装饰器的方法实现
作者:蠢萌的二狗子 时间:2022-08-04 13:06:10
LRU缓存算法,指的是近期最少使用算法,大体逻辑就是淘汰最长时间没有用的那个缓存,这里我们使用有序字典,来实现自己的LRU缓存算法,并将其包装成一个装饰器。
1、首先创建一个my_cache.py文件 编写自己我们自己的LRU缓存算法,代码如下:
import time
from collections import OrderedDict
'''
基于LRU,近期最少用缓存算法写的装饰器。
'''
class LRUCacheDict:
def __init__(self, max_size=1024, expiration=60):
self.max_size = max_size
self.expiration = expiration
self._cache = {}
self._access_records = OrderedDict() # 记录访问时间
self._expire_records = OrderedDict() # 记录失效时间
def __setitem__(self, key, value): # 设置缓存
now = int(time.time())
self.__delete__(key) # 删除原有使用该Key的所有缓存
self._cache[key] = value
self._access_records = now # 设置访问时间
self._expire_records = now + self.expiration # 设置过期时间
self.cleanup()
def __getitem__(self, key): # 更新缓存
now = int(time.time())
del self._access_records[key] # 删除原有的访问时按
self._access_records[key] = now
self.cleanup()
def __contains__(self, key): # 这个是字典默认调用key的方法
self.cleanup()
return key in self._cache
def __delete__(self, key):
if key in self._cache:
del self._cache[key] # 删除缓存
del self._access_records[key] # 删除访问时间
del self._expire_records[key] # 删除过期时间
def cleanup(self): # 用于去掉无效(超过大小)和过期的缓存
if self._expire_records is None:
return None
pending_delete_keys = []
now = int(time.time())
for k, v in self._expire_records.items(): # 判断缓存是否失效
if v < now:
pending_delete_keys.append(k)
for del_k in pending_delete_keys:
self.__delete__(del_k)
while len(self._cache) > self.max_size: # 判断缓存是否超过长度
for k in self._access_records.keys(): # LRU 是在这里实现的,如果缓存用的最少,那么它存入在有序字典中的位置也就最前
self.__delete__(k)
break
代码逻辑其实很简单,上面的注释已经很详细了,不懂的话多看几次。这里实现LRU逻辑的其实是有序字典OrderedDict,你最先存入的值就会存在字典的最前面。当一个值使用时候,我们会重新储存过期时间,导致被经常使用的缓存,会存在字典的后面。而一但缓存的内容长度超过限制时候,这里会调用有序字典最前面的key(也即是近期相对用的最少的),并删除对应的内容,以达到LRU的逻辑。
2、在将我们写好的算法改成装饰器:
from functools import wraps
from my_cache import LRUCacheDict
def lru_cache(max_size=1024, expiration=60, types='LRU'):
if types == 'lru' or types == 'LRU':
my_cache = LRUCacheDict(max_size=max_size, expiration=expiration)
def wrapper(func):
@wraps(func)
def inner(*args, **kwargs):
key = repr(*args, **kwargs)
try:
result = my_cache[key]
except KeyError:
result = func(*args, **kwargs)
my_cache[key] = result
return result
return inner
return wrapper
这里需要解释的是直接使用 my_cache[key],这个类似字典的方法,实际上是调用了 LRUCacheDict 中的 __contations__方法,这也是字典中实现通过key取值的方法。这个装饰器里,我加入了types的参数,你们可以根据需求,实现不同的缓存算法,丰富这个装饰器的功能,而lru缓存本身,其实已经是python的标准库了,可以引入functools.lru_cache来调用。
来源:https://blog.csdn.net/qq442000755/article/details/122150012
标签:Python,LRU,缓存装饰器
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
javascript 模拟函数指针
2009-09-19 18:02:00
Python产生batch数据的操作
2022-11-22 16:00:59
python神经网络学习利用PyTorch进行回归运算
2023-02-24 13:30:47
如何实现SQL Server的分页显示?
2010-05-18 18:36:00
Python seaborn barplot画图案例
2023-11-07 00:50:55
![](https://img.aspxhome.com/file/2023/7/63977_0s.png)
php curl登陆qq后获取用户信息时证书错误
2023-11-15 08:23:39
PHP children()函数讲解
2023-06-13 04:38:38
![](https://img.aspxhome.com/file/2023/9/55409_0s.png)
asp如何终止浏览器的 CAHCE 页面?
2010-07-07 12:25:00
利用Python pyecharts绘制饼图
2023-06-13 08:56:21
![](https://img.aspxhome.com/file/2023/1/68431_0s.png)
python爬虫用scrapy获取影片的实例分析
2023-09-25 09:22:30
![](https://img.aspxhome.com/file/2023/1/71581_0s.png)
python读写配置文件操作示例
2021-12-12 03:51:29
ASP中遍历和操作Application对象的集合
2007-09-13 12:45:00
MenuEverywhere 程序图标设计
2011-08-14 06:57:23
有效地使用 SQL事件探查器的提示和技巧
2009-01-15 13:39:00
内联格式化模式(line-height原理)
2008-06-29 14:37:00
ASP网站程序自动升级实现的方法
2008-10-15 14:28:00
CSS教程:简单理解em
2008-07-03 12:44:00
斜角滑动门导航条 DIV+CSS
2008-07-19 15:45:00
![](https://img.aspxhome.com/file/UploadPic/20087/19/200871916554645s.gif)
SQL Server中链接服务器将替代远程服务器
2009-06-15 11:03:00
numpy ndarray 按条件筛选数组,关联筛选的例子
2021-04-12 04:58:09