Python高级用法:装饰器用于缓存

缓存装饰器

缓存装饰器与参数检查十分相似,不过它重点是关注那些内部状态不会影响输出的函数。每组参数都可以链接到唯一的结果。这种编程风格是函数式编程的特点,当输入值有限时可以使用。

因此,缓存装饰器可以将输出与计算它所需要的参数放在一起,并在后续的调用中直接返回它。这种行为被称为memoizing。

例子

我们下面创建一个使用装饰器缓存技术,实现记录在一定时间内函数是否被调用的例子,来解释装饰器用于缓存的用法。

准备工作

首先我们准备引入相关的包,time用于获取当前时间,hashlib用于转换成哈希值,pickle用于将多个参数打包成一个对象,cache变量代表的是对函数返回值和时间的缓存。

python 复制代码
import time
import hashlib
import pickle

cache = {}

依赖函数

python 复制代码
def is_obsolete(entry, duration):
    return time.time() - entry['time'] > duration


def compute_key(function, args, kw):
    key = pickle.dumps((function.__name__, args, kw))
    return hashlib.sha1(key).hexdigest()

is_obsolete函数是用来比较上次函数访问时间(entry['time'],entry是一个字典,entry['time']存储的就是上次访问的时间)与当前时间(time.time())的间隔是否大于指定间隔(duration)的函数。

compute_key函数将传入的function,args,kw打包并转换成二进制形式,作为函数与参数对应的唯一标识。

构建修饰器

python 复制代码
def memoize(duration=10):
    def _memoize(function):
        def __memoize(*args, **kw):
            key = compute_key(function, args, kw)
            # 是否已经拥有它了?
            if (key in cache and
                    not is_obsolete(cache[key], duration)):
                print('we got a winner')
                return cache[key]['value']
            # 计算
            result = function(*args, **kw)
            # 保存结果
            cache[key] = {
                'value': result,
                'time': time.time()
            }
            return result
        return __memoize
    return _memoize

在__memoize函数中,先使用compute_key函数获取十六进制的哈希值,作为唯一关键词。然后查询是否存在于缓存中(cache)并且时间是否满足条件,如果均满足则直接返回上次的运行结果。否则重新计算结果并将结果存入缓存(cache)后返回。

测试

我们首先创建一个实现加法运算的函数

python 复制代码
@memoize()
def add(a, b):
    # 如果在执行这个计算时计算机过热
    # 请考虑中止程序
    return a + b

如果我们用以下代码测试

python 复制代码
print(add(1, 2))
print(add(1, 2))
print(add(2, 2))

得到的运行结果如下:

复制代码
3
we got a winner
3
4

第二次调用add(1, 2)时因为前面已经调用过了,所以就直接给出提示返回结果,而add(2, 2)是一个新的参数的运算,所以进行了再次重复的运算。

下面我们来看一下如果超时会有怎样的结果,由于默认的menoize参数是10,所以我们这里改成1

python 复制代码
@memoize(1) # 1秒后令缓存失效
def add(a, b):
    return a + b
    
print(add(2, 3))
time.sleep(2)
print(add(2, 3))

我们使用time.sleep沉睡两秒

运行结果是

复制代码
5
5
相关推荐
SmartRadio6 小时前
CH585M+MK8000、DW1000 (UWB)+W25Q16的低功耗室内定位设计
c语言·开发语言·uwb
rfidunion6 小时前
QT5.7.0编译移植
开发语言·qt
少林码僧6 小时前
2.31 机器学习神器项目实战:如何在真实项目中应用XGBoost等算法
人工智能·python·算法·机器学习·ai·数据挖掘
rit84324996 小时前
MATLAB对组合巴克码抗干扰仿真的实现方案
开发语言·matlab
智航GIS6 小时前
10.4 Selenium:Web 自动化测试框架
前端·python·selenium·测试工具
jarreyer6 小时前
摄像头相关记录
python
宝贝儿好6 小时前
【强化学习】第六章:无模型控制:在轨MC控制、在轨时序差分学习(Sarsa)、离轨学习(Q-learning)
人工智能·python·深度学习·学习·机器学习·机器人
大、男人6 小时前
python之asynccontextmanager学习
开发语言·python·学习
hqwest6 小时前
码上通QT实战08--导航按钮切换界面
开发语言·qt·slot·信号与槽·connect·signals·emit
AC赳赳老秦7 小时前
DeepSeek 私有化部署避坑指南:敏感数据本地化处理与合规性检测详解
大数据·开发语言·数据库·人工智能·自动化·php·deepseek