Python手动实现LRU缓存装饰器详解

追风的人
追风的人
发布时间:2026-10-15| 6人浏览过
原创

本文详细介绍如何在Python中手动实现LRU(最近最少使用)缓存装饰器。通过结合collections.OrderedDict与时间戳管理,文章展示了如何构建LRUCacheDict类以处理缓存大小限制与过期策略,并进一步将其封装为通用的装饰器函数。内容涵盖核心代码逻辑、参数配置及与标准库functools.lru_cache的对比,帮助开发者深入理解缓存机制并提升代码复用能力。

LRU缓存算法原理与装饰器概述

LRU(Least Recently Used)缓存算法的核心逻辑在于淘汰最久未被使用的缓存项。本文将利用Python的有序字典(OrderedDict)特性,手动实现这一算法,并将其封装为一个通用的装饰器,以便在函数调用中灵活应用。

LRUCacheDict类实现细节

首先,我们需要创建一个名为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

该代码的逻辑结构清晰,主要依赖于OrderedDict数据结构。OrderedDict能够保持键值对的插入顺序:新存入的值位于字典前端,而每次访问现有值时,其会被重新记录并移至字典后端。当缓存容量超过预设的最大限制时,系统会自动移除位于字典前端的键值对(即近期使用频率最低的项),从而严格遵循LRU淘汰策略。

装饰器封装与使用方式

接下来,我们将上述缓存逻辑封装为一个装饰器,以便直接应用于目标函数。

装饰器代码结构与参数解析


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类中的__getitem__方法,这是字典通过键取值的标准机制。此外,装饰器引入了types参数,允许用户根据需求扩展不同的缓存策略,从而丰富装饰器的功能。需要注意的是,Python标准库functools.lru_cache已提供成熟的LRU缓存功能,可直接引入使用,但手动实现有助于深入理解其内部机制。

至此,关于手动编写Python LRU缓存装饰器的完整实现与解析已介绍完毕。如需了解更多相关技术细节,建议查阅本站往期文章或持续关注后续更新。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。