Python 如何手动编写一个自己的LRU缓存装饰器的方法实现

 更新时间:2021年12月26日 16:48:53   作者:蠢萌的二狗子  
本文主要介绍了Python如何手动编写一个自己的LRU缓存装饰器,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

Python客栈送红包、纸质书

LRU缓存算法,指的是近期最少使用算法,大体逻辑就是淘汰最长时间没有用的那个缓存,这里我们使用有序字典,来实现自己的LRU缓存算法,并将其包装成一个装饰器。

1、首先创建一个my_cache.py文件 编写自己我们自己的LRU缓存算法,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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、在将我们写好的算法改成装饰器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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来调用。

到此这篇关于Python 如何手动编写一个自己的LRU缓存装饰器的方法实现的文章就介绍到这了,更多相关Python LRU缓存装饰器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

蓄力AI

微信公众号搜索 “ 脚本之家 ” ,选择关注

程序猿的那些事、送书等活动等着你

原文链接:https://blog.csdn.net/qq442000755/article/details/122150012

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 reterry123@163.com 进行投诉反馈,一经查实,立即处理!

相关文章

  • Python enumerate函数功能与用法示例

    Python enumerate函数功能与用法示例

    这篇文章主要介绍了Python enumerate函数功能与用法,结合实例形式分析了enumerate函数针对列表、字符串遍历操作相关使用技巧,需要的朋友可以参考下
    2019-03-03
  • pyTorch深入学习梯度和Linear Regression实现

    pyTorch深入学习梯度和Linear Regression实现

    这篇文章主要介绍了pyTorch深入学习,实现梯度和Linear Regression,文中呈现了详细的示例代码,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-09-09
  • Python语法学习之线程的创建与常用方法详解

    Python语法学习之线程的创建与常用方法详解

    本文主要介绍了线程的使用,线程是利用进程的资源来执行业务,并且通过创建多个线程,对于资源的消耗相对来说会比较低,今天就来看一看线程的使用方法具体有哪些吧
    2022-04-04
  • 4种非常实用的python内置数据结构

    4种非常实用的python内置数据结构

    这篇文章主要介绍了4种非常实用的python内置数据结构,帮助大家更好的理解和学习使用python,感兴趣的朋友可以了解下
    2021-04-04
  • Spectral clustering谱聚类算法的实现代码

    Spectral clustering谱聚类算法的实现代码

    谱聚类是从图论中演化出来的算法,它的主要思想是把所有的数据看做空间中的点,这些点之间可以用边连接起来,今天通过本文给大家介绍Spectral clustering谱聚类算法的实现,感兴趣的朋友一起看看吧
    2022-04-04
  • Python使用pyodbc访问数据库操作方法详解

    Python使用pyodbc访问数据库操作方法详解

    这篇文章主要介绍了Python使用pyodbc访问数据库操作方法,结合实例形式详细分析了Python基于pyodbc针对数据库的连接、查询、插入、修改、删除等操作技巧与注意事项,需要的朋友可以参考下
    2018-07-07
  • python学生信息管理系统(初级版)

    python学生信息管理系统(初级版)

    这篇文章主要为大家详细介绍了python学生信息管理系统的初级版本代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • Python Django给admin添加Action的方法实例详解

    Python Django给admin添加Action的方法实例详解

    这篇文章主要介绍了Django给admin添加Action的方法,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-04-04
  • python使用期物处理并发教程

    python使用期物处理并发教程

    这篇文章主要为大家介绍了python使用期物处理并发教程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • 用Python实现命令行闹钟脚本实例

    用Python实现命令行闹钟脚本实例

    今天我们讲一下用Python写的一个小脚本。这是一个可以在命令行运行的闹钟脚本,对于日常大家工作很实用,有需要的朋友们可以参考借鉴。
    2016-09-09

最新评论