首页 > 编程问答 >关于 Python 中装饰器缓存的困惑

关于 Python 中装饰器缓存的困惑

时间:2024-07-25 14:24:23浏览次数:12  
标签:python function caching arguments decorator

我正在使用 Python 装饰器来实现函数的缓存。我了解缓存结果以提高性能的基本概念,但我正在努力解决如何处理不同的函数参数并确保底层数据更改时缓存更新。

我已经实现了一个基本装饰器,它将函数结果存储在基于参数的字典。但是,此方法无法处理函数参数可能具有复杂结构(如嵌套列表)或函数依赖的基础数据可能被修改的情况。

`def simple_cache(func): 缓存={} def 包装器(*args,**kwargs): key = (args, kwargs) # 基于参数的基本键 如果密钥不在缓存中: 缓存[键] = func(*args, **kwargs) 返回缓存[key] 返回包装

@simple_cache defcalculate_something(data):

模拟复杂计算

...

返回结果 `


对 Python 装饰器缓存的理解非常好,并且已经确定了使用简单字典作为缓存机制的局限性。让我们来解决这些局限性,并探索一些更强大的缓存技术:

1. 处理复杂参数

  • 哈希: 不是直接使用可变结构(如列表或字典)作为键,而是使用哈希函数。 Python 的内置 hash() 函数可以处理不可变类型,但对于可变结构,需要一个强大的哈希函数,比如来自 hashlib 的函数。但是,确保的哈希函数适合的数据类型,并且可以很好地防止冲突。

```python import hashlib

def simple_cache(func): cache = {} def wrapper( args, kwargs): key = hashlib.md5(str((args, kwargs)).encode()).hexdigest() # 创建更稳定的哈希 if key not in cache: cache[key] = func( args, **kwargs) return cache[key] return wrapper ```

  • 参数序列化: 另一个选择是使用 pickle json 等模块将参数序列化为不可变字符串。这在处理复杂结构时效果很好,但会带来额外的开销。

```python import json

def simple_cache(func): cache = {} def wrapper( args, kwargs): key = json.dumps((args, kwargs)) if key not in cache: cache[key] = func( args, **kwargs) return cache[key] return wrapper ```

2. 处理数据更改

  • 基于时间的失效: 为缓存条目设置过期时间,以便在设定的时间间隔后刷新它们。这可以通过使用 time 模块或为每个缓存条目存储时间戳来实现。

```python import time

def timed_cache(seconds=300): # 默认缓存时间为 5 分钟 def decorator(func): cache = {} def wrapper( args, kwargs): key = (args, kwargs) now = time.time() if key not in cache or now - cache[key][1] > seconds: cache[key] = (func( args, **kwargs), now) return cache[key][0] return wrapper return decorator ```

  • 基于事件的失效: 当知道依赖的数据已更改时,手动使缓存失效。这需要更复杂的设置,但可以实现更精细的控制。可以引入一个机制,在基础数据更新时清除缓存或使特定条目无效。

```python def event_based_cache(cache): # 使用共享缓存 def decorator(func): def wrapper( args, kwargs): key = (args, kwargs) if key not in cache: cache[key] = func( args, **kwargs) return cache[key] return wrapper

# 在其他地方,当数据更改时: cache.clear() # 或使特定键无效 ```

3. 使用 functools.lru_cache

Python 的标准库提供了 functools.lru_cache 装饰器,它可以处理缓存,包括基于最近最少使用 (LRU) 算法的自动失效。这是一个高效且易于使用的选择,尤其是对于一般的缓存目的。

from functools import lru_cache

@lru_cache(maxsize=128)  # 缓存最多 128 个结果
def calculate_something(data):
    # ...
    return result

请记住,最佳缓存策略取决于的具体需求和应用程序的行为。仔细考虑参数的性质、数据更改的频率以及所需的缓存失效级别。

标签:python,function,caching,arguments,decorator
From: 78791684

相关文章

  • Python:__add__ 和 +,浮点数和整数的不同行为
    当将整数值添加到浮点值时,我意识到如果在浮点上调用该方法可以正常工作,例如:__add__但如果在整数上调用则不行:>>>n=2.0>>>m=1>>>n.__add__(m)3.0起初我认为|||只是对>>>m.__add__(n)NotImplemented和__add__类型的实现方式不同(例如f......
  • python中scrapy爬取数据get()与getall()区别
    在使用scrapy进行爬取数据的时候,有些时候需要爬取的是一段文本,或者一个div里面有很多内容,这时候我们就要使用到get()或者getall()来获取数据: get():是获取的满足条件的第一个数据。getall():是获取的满足条件的所有数据。scrapyget()getall()原理在Scrapy中,get(......
  • python—NumPy基础(3)
    文章目录算术函数算术函数的使用算术函数中out参数的使用mod()函数的使用统计函数power()函数的使用median()函数的使用mean()函数的使用函数的使用其他常用函数tile()和repeat()函数的使用roll()函数的使用resize()函数的使用replace()和put()函数的使savetxt()和lo......
  • Python爬虫:代理ip电商数据实战
    引言:数据访问管理引发的烦恼作为一名Python博主,爬虫技能对于获取和分析数据至关重要,经常爬一下,有益身心健康嘛。爬虫技术对很多人来说,不仅仅是一种工具,更像是一种艺术,帮助我们从互联网中,捕捉到有价值的信息。我经常就会用爬虫来爬取一些所需的数据,用来进行数据分析和模型训......
  • python科学计算:加速库numba —— 安装和试用
    安装(anaconda环境下)condainstallnumbaDemo代码:fromnumbaimportjitfromnumpyimportarangeimportnumpyimporttime@jitdefsum2d(arr):M,N=arr.shaperesult=0.0foriinrange(M):forjinrange(N):result+=a......
  • Python - Selenium抓取淘宝直播间评论(可使用无头模式)
    Python-Selenium抓取淘宝直播间评论(可使用无头模式)下面介绍如何使用python中的selenium简单抓取淘宝直播间实时评论。友情提醒,仅供学习交流使用,请勿用于非法用途!一、创建python项目1.在目录下新建main.py和venv虚拟环境:创建虚拟环境:python-mvenvvenv激活虚拟环......
  • 需要帮助来提取此 XML 节点 - Python 中的 Excel 连接字符串
    我有一个Python程序,打开Excel(XLSX)文件,并尝试查找<connection>节点。这是connections.xml文件中的完整XML。<?xmlversion="1.0"encoding="UTF-8"standalone="yes"?><connectionsxmlns="http://schemas.op......
  • 【python】Python中采集Prometheus数据,进行数据分析和可视化展示
    ✨✨欢迎大家来到景天科技苑✨✨......
  • 使用python3拼接rgb.txt与depth.txt为associate.txt(适用于GCNV2_SLAM中TUM数据集的运
    这里以GCNV2_SLAM中TUM数据集的运行为例子:安装gnv2_slam可以参考:GCNv2_SLAM-CPU详细安装教程(ubuntu18.04)-CSDN博客首先下载数据集ComputerVisionGroup-DatasetDownload下载后通过该命令解压:tar-xvfrgbd_dataset_freiburg1_desk.tgz打开后,你可以发现:在该数据集......
  • 【Python】到底什么是字符串格式化?
    字符串格式化的目的:在字符串中动态地插入数据或表达式。字符串格式化的对象:要插入到字符串中的数据。在详细解释之前,先引入第一种字符串格式化的方法name=input('请输入你的名字:')gender=input('请输入你的性别:')age=input('请输入你的年龄:')print(f'你的名字是{......