想要手动编写一个自己的LRU缓存装饰器,需要遵循以下几个步骤:
- 导入functools和collections模块
在Python中,functools模块用于操作函数,collections模块用于提供容器类型,如有序字典(OrderedDict)等。
import functools
import collections
- 定义装饰器函数
通过定义一个包装器函数,在函数执行前先检查是否已经存在缓存数据。若存在,则直接返回缓存的值,否则执行函数,并将其返回值加入缓存。
def lru_cache(max_size):
"""LRU缓存装饰器"""
def decorator(func):
cache = collections.OrderedDict() # 设置有序字典缓存
@functools.wraps(func)
def wrapper(*args, **kwargs):
key = args + tuple(kwargs.items()) # 将参数和关键字参数组成元组作为缓存的键
if key in cache:
# 如果键已经存在,则将它移到有序字典的末尾,并将缓存值返回
value = cache.pop(key)
cache[key] = value
else:
# 如果键不存在,则执行函数,将返回值存入缓存
value = func(*args, **kwargs)
cache[key] = value
# 如果缓存的键值对数量超过了max_size,则从有序字典的头部开始删除键值对,直到数量小于等于max_size
if len(cache) > max_size:
cache.popitem(last=False)
return value
return wrapper
return decorator
该装饰器函数可以接受一个最大缓存数量的参数,以及一个待装饰的函数。定义缓存时使用了有序字典,它可以按照键值对的插入顺序维护字典中元素的顺序。在wrapper函数中,先将函数的参数和关键字参数组成元组作为缓存的键,先根据键值查找是否存在缓存数据。如果缓存数据已经存在,则先将该键对应的值移动到有序字典的最后,以便于维护其访问顺序;如果缓存数据不存在,则需要执行函数,并缓存返回值,则将键值对添加到有序字典中,并根据最大缓存数量的设定,决定是否要删除最早的缓存数据。
- 使用装饰器
使用装饰器,在函数调用的时候可以自动地完成缓存的功能。
示例1:对于输入的参数,进行累加操作,去重后返回
@lru_cache(max_size=2)
def calculate(a,b,c):
return sum(set([a,b,c]))
print(calculate(1, 2, 3)) # 计算并缓存,返回6
print(calculate(1, 2, 3)) # 直接从缓存中返回6
print(calculate(2, 3, 4)) # 计算并缓存,因为缓存达到最大数量,删除最早的缓存
print(calculate(1, 2, 3)) # 由于之前的计算结果已经被缓存,因此可以直接从缓存中返回6
示例2:对于输入的参数,将输入项中各单词翻转后再返回
@lru_cache(max_size=4)
def reverse_words(s):
return ' '.join([word[::-1] for word in s.split()])
print(reverse_words('Hello World')) # 计算并缓存,返回"olleH dlroW"
print(reverse_words('Hello Nice to Meet You')) # 计算并缓存,返回"olleH eciN ot teeM uoY"
print(reverse_words('Hello World')) # 直接从缓存中返回之前的结果"olleH dlroW"
print(reverse_words('Nice to Meet You Friend')) # 计算并缓存,由于缓存已经满了,删除最早的缓存,返回"eciN ot teeM uoY dneirF"
print(reverse_words('Nice to Meet You')) # 计算并缓存,由于缓存已经满了,删除最早的缓存,返回"eciN ot teeM uoY"
print(reverse_words('Hello Nice to Meet You')) # 直接从缓存中返回之前的结果"olleH eciN ot teeM uoY"
在上述示例中,对于输入的不同参数,进行缓存,当达到缓存上限时,最早的缓存会被删除,并不断向有序字典的末尾插入新的缓存数据。从而实现了LRU缓存的功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python 如何手动编写一个自己的LRU缓存装饰器的方法实现 - Python技术站