Python LRU 缓存的实现原理
发布时间 - 2026-01-29 00:00:00 点击率:次LRU缓存必须用双向链表+哈希表,因单纯dict无法O(1)删除最久未使用项;双向链表支持O(1)节点移动,哈希表提供O(1)查找,二者协同实现get/put的常数时间复杂度。
LRU 缓存为什么必须用双向链表 + 哈希表
单纯用 dict 无法在 O(1) 时间内删除最久未使用的项,因为 Python 字典不保证访问顺序(3.7+ 虽然有序,但“最近访问”和“插入顺序”不是一回事)。LRU 的核心操作——把某 key 移到“最近使用”位置、删掉“最久未使用”节点——需要常数时间定位 + 删除 + 插入。双向链表支持 O(1) 拆入节点,哈希表提供 O(1) 查找节点指针。
常见错误是只用 OrderedDict 的 move_to_end(),它确实能模拟 LRU,但底层仍是链表操作,且每次访问都触发重排;而手写结构可避免冗余移动(比如只在 get 时更新,put 冲突时才删尾)。
Python 标准库 functools.lru_cache 怎么做缓存淘汰
它不公开内部链表,但行为等价:调用函数时命中缓存 → 把对应 entry 移至链表头;新 entry 插入头;容量超限时删链表尾。关键点在于它用弱引用(weakref)管理参数哈希键,避免因缓存导致对象无法回收。
实操注意:
-
lru_cache(maxsize=128)中maxsize=None表示无限制,但实际仍受内存约束 - 被装饰函数的参数必须可哈希(否则抛
TypeError: unhashable type),比如不能传list或dict - 线程安全:内部用
RLock,多线程下调用不会崩,但高并发下锁争用会影响吞吐
手动实现 LRU 时最容易漏掉的边界条件
自己写 LRUCache 类时,90% 的 bug 出在节点操作的对称性上:插入新节点要同时更新哈希表和链表;删除节点要从两者中都清除;更新访问顺序时不能只改链表而忘了哈希表里存的还是旧节点指针。
典型坑:
- 初始化时没设好虚拟头尾节点(
self.head/self.tail),导致get空缓存时
next为None报AttributeError -
put时 key 已存在,只更新 value 却忘了把节点移到头部 - 容量为 0 时,任何
put都应直接丢弃,不进缓存也不触发淘汰
一个最小可用骨架的关键逻辑是:self.cache[key] = new_node 必须紧挨着 self._add_to_head(new_node),顺序反了就会缓存错位。
lru_cache 的性能开销主要在哪
不是哈希计算,也不是链表操作,而是函数调用前后的封装层:每次调用都要走 descriptor 协议、检查参数 hash、查表、计数器更新、可能的锁获取。实测显示,空函数加 @lru_cache() 后调用耗时增加 3–5 倍(纳秒级变几十纳秒)。
所以别给单次运行就结束的函数加缓存;更别给参数总在变的函数加(比如含 time.time() 或随机数);如果函数本身耗时远低于 100ns,缓存反而拖慢整体。
真正值得缓存的是:纯函数、参数组合有限、执行成本显著高于哈希与查表(如 IO、复杂计算、数据库查询封装)。
# python
# node
# ai
# 标准库
# 为什么
# red
# 封装
# 指针
# 线程
# 多线程
# 并发
# 对象
# 数据库
# bug
# 链表
# 最久
# 移到
# 的是
# 就会
# 也不
# 随机数
# 时间内
# 仍是
# 怎么做
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?
Laravel中Service Container是做什么的_Laravel服务容器与依赖注入核心概念解析
Python自动化办公教程_ExcelWordPDF批量处理案例
Laravel如何使用Spatie Media Library_Laravel图片上传管理与缩略图生成【步骤】
Laravel队列任务超时怎么办_Laravel Queue Timeout设置详解
Laravel怎么配置自定义表前缀_Laravel数据库迁移与Eloquent表名映射【步骤】
微信小程序 scroll-view组件实现列表页实例代码
edge浏览器无法安装扩展 edge浏览器插件安装失败【解决方法】
如何用已有域名快速搭建网站?
Laravel怎么防止CSRF攻击_Laravel CSRF保护中间件原理与实践
如何在阿里云通过域名搭建网站?
Laravel Pest测试框架怎么用_从PHPUnit转向Pest的Laravel测试教程
Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】
如何快速打造个性化非模板自助建站?
如何快速生成专业多端适配建站电话?
Laravel控制器是什么_Laravel MVC架构中Controller的作用与实践
Javascript中的事件循环是如何工作的_如何利用Javascript事件循环优化异步代码?
如何用y主机助手快速搭建网站?
Laravel项目结构怎么组织_大型Laravel应用的最佳目录结构实践
西安专业网站制作公司有哪些,陕西省建行官方网站?
Laravel API资源(Resource)怎么用_格式化Laravel API响应的最佳实践
IOS倒计时设置UIButton标题title的抖动问题
高防服务器租用首荐平台,企业级优惠套餐快速部署
MySQL查询结果复制到新表的方法(更新、插入)
JS经典正则表达式笔试题汇总
制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?
网页设计与网站制作内容,怎样注册网站?
Python面向对象测试方法_mock解析【教程】
家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?
百度输入法ai组件怎么删除 百度输入法ai组件移除工具
米侠浏览器网页背景异常怎么办 米侠显示修复
如何在万网主机上快速搭建网站?
Laravel怎么配置.env环境变量_Laravel生产环境敏感数据保护与读取【方法】
谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复
湖南网站制作公司,湖南上善若水科技有限公司做什么的?
Laravel如何创建和注册中间件_Laravel中间件编写与应用流程
如何用wdcp快速搭建高效网站?
购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?
Laravel怎么使用artisan命令缓存配置和视图
详解Oracle修改字段类型方法总结
Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧
Laravel Eloquent模型如何创建_Laravel ORM基础之Model创建与使用教程
Laravel如何正确地在控制器和模型之间分配逻辑_Laravel代码职责分离与架构建议
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
Laravel如何处理JSON字段_Eloquent原生JSON字段类型操作教程
使用C语言编写圣诞表白程序
微信小程序 canvas开发实例及注意事项
浅述节点的创建及常见功能的实现
Laravel如何记录日志_Laravel Logging系统配置与自定义日志通道
如何快速生成ASP一键建站模板并优化安全性?


