Python手动实现LRU缓存装饰器详解
本文详细介绍如何在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缓存装饰器的完整实现与解析已介绍完毕。如需了解更多相关技术细节,建议查阅本站往期文章或持续关注后续更新。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









