Python内置的lru_cache装饰器实现缓存教程

news/2025/11/25 22:35:49/文章来源:https://www.cnblogs.com/bukfz/p/19270327

functools.lru_cache 是 Python 内置的函数缓存装饰器,基于「最近最少使用(LRU)」策略管理缓存,能自动缓存函数的调用结果,避免重复执行高耗时函数(如复杂计算、数据库查询)。以下是它的完整使用指南,包含基础用法、进阶技巧和注意事项。

一、核心原理

  • lru_cache 会记录函数的入参和对应的返回值,当函数以相同参数再次调用时,直接返回缓存的结果,无需重新执行函数。
  • 当缓存达到指定上限(maxsize),会自动淘汰「最近最少使用」的缓存条目,避免内存无限占用。

二、基础使用步骤

1. 导入模块

lru_cache 位于 functools 模块,需先导入:

from functools import lru_cache

2. 装饰函数

@lru_cache 装饰需要缓存的函数,核心参数:

参数 说明
maxsize 缓存的最大条目数(默认128;设为 None 表示无限制,禁用LRU淘汰)
typed 是否区分参数类型(默认False;设为True时,11.0 会被视为不同参数)

3. 基础示例:缓存复杂计算

from functools import lru_cache
import time# 装饰器:缓存函数结果,无缓存数量限制,不区分参数类型
@lru_cache(maxsize=None, typed=False)
def complex_calc(n):"""模拟耗时计算:计算n的阶乘(递归)"""time.sleep(1)  # 模拟1秒耗时if n == 0 or n == 1:return 1return n * complex_calc(n - 1)# 测试:首次调用(耗时)
start = time.time()
print(complex_calc(5))  # 输出120,耗时约5秒(递归5次,每次1秒)
print(f"首次调用耗时:{time.time() - start:.2f}秒")# 测试:重复调用(命中缓存,瞬间返回)
start = time.time()
print(complex_calc(5))  # 直接返回缓存结果120
print(f"缓存调用耗时:{time.time() - start:.2f}秒")

输出结果:

120
首次调用耗时:5.01秒
120
缓存调用耗时:0.00秒

三、常用进阶用法

1. 查看/清空缓存

lru_cache 为装饰后的函数提供了两个实用方法:

  • cache_info():返回缓存统计信息(命中数、未命中数、最大容量、当前缓存数);
  • cache_clear():清空所有缓存。

示例:

from functools import lru_cache@lru_cache(maxsize=10)
def add(a, b):return a + b# 调用函数,触发缓存
add(1, 2)
add(1, 2)
add(3, 4)# 查看缓存信息
print(add.cache_info())
# 输出:CacheInfo(hits=1, misses=2, maxsize=10, currsize=2)
# hits=1:1次命中;misses=2:2次未命中;currsize=2:当前缓存2条# 清空缓存
add.cache_clear()
print(add.cache_info())
# 输出:CacheInfo(hits=0, misses=0, maxsize=10, currsize=0)

2. 缓存带参数的数据库查询(模拟)

适合缓存「输入固定、输出固定」的查询操作,减少数据库访问:

from functools import lru_cache# 模拟数据库查询(高耗时操作)
def query_db(user_id):print(f"[数据库查询] user_id={user_id}")return {"id": user_id, "name": f"User{user_id}", "age": 20 + user_id}# 缓存查询结果(仅缓存可哈希参数)
@lru_cache(maxsize=100)
def get_user(user_id):return query_db(user_id)# 测试
print(get_user(1))  # 未命中,执行数据库查询
print(get_user(1))  # 命中缓存,直接返回
print(get_user(2))  # 未命中,执行数据库查询

输出:

[数据库查询] user_id=1
{'id': 1, 'name': 'User1', 'age': 21}
{'id': 1, 'name': 'User1', 'age': 21}
[数据库查询] user_id=2
{'id': 2, 'name': 'User2', 'age': 22}

3. 处理不可哈希参数(如列表/字典)

lru_cache 仅支持可哈希参数(如int、str、tuple),若函数参数是列表/字典(不可哈希),需先转为可哈希类型(如tuple):

from functools import lru_cache# 错误示例:参数为列表(不可哈希),会报错
# @lru_cache
# def sum_list(lst):
#     return sum(lst)# 正确示例:将列表转为元组(可哈希)
@lru_cache(maxsize=None)
def sum_list(lst_tuple):return sum(lst_tuple)# 调用时将列表转为元组
lst = [1, 2, 3]
print(sum_list(tuple(lst)))  # 6
print(sum_list(tuple(lst)))  # 命中缓存,直接返回

4. 区分参数类型(typed=True)

默认情况下 typed=False1(int)和 1.0(float)会被视为相同参数;设为 typed=True 则区分类型:

from functools import lru_cache@lru_cache(typed=True)
def add(a, b):return a + bprint(add(1, 2))   # 未命中,返回3
print(add(1.0, 2.0))  # 未命中,返回3.0(typed=True,视为不同参数)
print(add.cache_info())  # hits=0, misses=2

四、关键注意事项

1. 仅适用于「纯函数」

lru_cache 缓存的是「入参→返回值」的映射,仅对纯函数(输入固定则输出固定,无副作用)有效:

  • ❌ 不适合带随机值、时间依赖、全局变量的函数(如 def get_time(): return time.time());
  • ❌ 不适合修改外部状态的函数(如操作数据库/文件的函数,除非仅查询)。

2. 避免缓存大对象/无限缓存

  • maxsize=None 会禁用LRU淘汰,缓存会无限增长,可能导致内存泄漏(适合少量固定参数的场景);
  • 避免缓存大对象(如超大列表、大字典),优先缓存小而高频的结果。

3. 程序重启后缓存丢失

lru_cache进程内内存缓存,程序重启/进程结束后缓存会清空,若需持久化/分布式缓存,需用 Redis 等工具。

4. 递归函数的缓存优化

lru_cache 对递归函数优化效果显著(如斐波那契数列),避免重复递归计算:

from functools import lru_cache@lru_cache(maxsize=None)
def fibonacci(n):if n <= 1:return nreturn fibonacci(n-1) + fibonacci(n-2)# 计算第50项(无缓存会卡死,有缓存瞬间返回)
print(fibonacci(50))  # 12586269025

五、总结

lru_cache 是 Python 最简单、最高效的内置缓存工具,核心用法:

  1. 导入 from functools import lru_cache
  2. 装饰纯函数,通过 maxsize 控制缓存容量,typed 控制类型区分;
  3. cache_info() 监控缓存命中率,cache_clear() 清空缓存;
  4. 仅缓存可哈希参数,不可哈希参数需先转换(如列表→元组)。

适合场景:单进程、无过期时间、纯函数的缓存需求;若需过期时间/分布式缓存,需用 cachetools/Redis 等扩展方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/976543.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年轮胎品牌推荐:权威TOP10全球品牌综合排名

2025年轮胎品牌推荐:权威TOP10全球品牌综合排名在当前汽车消费加速升级与新能源浪潮席卷的时代背景下,“轮胎品牌推荐”已成为广大车主、整车厂商及资本市场研判赛道格局的核心议题。面对琳琅满目的品牌阵列与繁杂的…

详细介绍:Git分支合并实战指南:从feature到master,一文搞定全流程!

详细介绍:Git分支合并实战指南:从feature到master,一文搞定全流程!pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: &…

北京墙体彩绘公司推荐香鲸艺术坊,行业排名遥遥领先!

墙体彩绘作为空间美学升级的核心方式,在北京商业场景引流、家装个性定制、政企文化建设等领域需求持续攀升。本文基于市场口碑调研、服务案例落地、环保资质审核、售后保障能力四大核心维度,整理出北京墙体彩绘行业综…

虚拟科学峰会推动技术交流创新

文章探讨了疫情期间科学会议向虚拟形式转变的趋势,重点分析了某中心消费者科学峰会的线上举办经验,涉及机器学习、优化算法等技术领域,并讨论了虚拟会议对科研协作模式带来的深远影响。虚拟科学会议:技术驱动的新交…

java---gradle配置国内镜像

在进行java开发项目的时候,相比maven来说,gradle更好用一些。但是由于服务器在国外,下载资源就很慢,超时还会报异常。 方法一:使用本地Gradle打开腾讯云Gradle镜像页面:https://mirrors.cloud.tencent.com/gradl…

2025年11月南京装修公司综合实力排行榜(品牌智鉴榜推荐)

品牌智鉴榜评测,2025年11月,品牌智鉴榜联合第三方权威测评机构,基于设计能力、施工品质、售后响应、价格透明度等12项核心指标,完成对全市60余家正规装修企业的综合测评,发布《2025年11月南京装修公司综合实力排行…

揭开Claude Opus 4.5神秘面纱

揭开Claude Opus 4.5神秘面纱一位对 AI 充满好奇的学习者——揭开 Claude Opus 4.5 的神秘面纱,清晰展示它在软件工程、安全性和多语言处理等领域取得的革命性进步。1. 软件工程领域的“超强大脑”无人能及的工程能力…

Image图片组件基础加载与属性设置

# Image图片组件基础加载与属性设置 ## 前言 在HarmonyOS应用开发中,Image组件是展示图片内容的核心组件。本文将全面讲解Image组件的各种使用方法和属性设置,帮助开发者快速掌握图片显示的相关技能。 **官方参考资料…

2025年新能源汽车轮胎推荐:独家负载与静音测评报告

2025年新能源汽车轮胎推荐:独家负载与静音测评报告在新能源汽车渗透率持续攀升的背景下,如何解决用户在“新能源汽车轮胎推荐”上的选择难题,已成为关乎每一位车主出行品质的核心议题。相较于传统燃油车,新能源车因…

11月25日日记

1.今天上午工程实训,下午英语视听说 2.明天上马哲 3.@RequestParam 和 @RequestBody 的使用场景区别?JSON 数据如何正确接收?

CF370A-Rook, Bishop and King

CF370A-Rook, Bishop and King 题目大意 国际象棋棋盘上有两个位置,现在问一个车,象和王,从一个位置走到另一个位置的最少移动次数。 题解 对于所有,如果两个点重合,则都为 \(0\) 。 对于车,如果同行同列则为 \(…

实用指南:基于“开源AI智能名片链动2+1模式S2B2C商城小程序”的会员制培养策略研究

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年越野轮胎推荐:十大专业品牌最新全地形解析

2025年越野轮胎推荐:十大专业品牌最新全地形解析为解决用户在“越野轮胎推荐”上的选择难题,本文将基于全球主流汽车媒体(如《AutoBild》、汽车之家等)的公开评测模型与数据,从以下四大核心维度,对市场上的主流旗…

11月25日

上午工程实训,下午英语课

Switch大气层20-整合包1-9-0测试版

switch大气层; switch大气层21.0.0系统更新测试版整合包; Switch20.0.1系统整合包; 大气层整合包1.10.0测试版; 支持最新的21.0.0等固件系统版本朗读全文Your browser does not support the audio element. 有什么…

2025年家用轿车轮胎推荐:权威综合排名与选购指南

2025年家用轿车轮胎推荐:权威综合排名与选购指南面对当下家用车市场对轮胎选择日益严苛的需求,如何在琳琅满目的产品中挑选出真正契合“家用轿车轮胎推荐”这一命题的旗舰之作,已成为困扰无数消费者的现实难题。为解…

第三次作业-何玮鑫

作业3 中国气象网图片爬取实验 一、实验目的 通过实现单线程和多线程两种爬取方式,对比不同并发策略在网络图片下载任务中的效率差异,深入理解多线程编程在 IO 密集型任务中的优势,掌握requests、BeautifulSoup、Th…

基于.net6的一款开源的低代码、权限、工作流、动态接口平台-系统安装篇

系统安装说明 1. 安装环境操作系统:Windows 10 或以上版本 数据库:MySQL 8.0 或以上版本(我开发使用的是Windows版本,Linux版本没有测试) .NET 6.0 Yarn:1.22 或以上版本2. 拉取项目代码 2.1 命令行拉取项目代码打…

macOS开启自带的TFTP Server

macOS开启自带的TFTP ServerPosted on 2025-11-25 22:06 shenyixin 阅读(0) 评论(0) 收藏 举报macOS开启内建的TFTP服务器 1.开启 TFTP 服务打开「终端」,执行以下命令(需要管理员密码): sudo launchctl load…

AT_arc178_c [ARC178C] Sum of Abs 2

感觉思路很顺。 首先绝对值讨论很麻烦,考虑钦定 \(B\) 单调不降。容易得到贡献式子 \(S=\sum_{i=1}^{L-1}(i-2)B_i+(L-1)B_L\)。 有个 trick,单调不降的序列可以看作多次后缀 +1 得到(单调不升同理)。而对后缀 \([…