Python 用 @cached_property 缓存实例属性:惰性计算、什么时候失效,以及它不是线程安全的
Python 用 cached_property 缓存实例属性:惰性计算、什么时候失效,以及它不是线程安全的你写了个类,里面有个属性算起来很贵——要读文件、查数据库、跑一段复杂计算。结果每次访问obj.data都重新算一遍,一个请求里访问五次就白算四次。很多人第一反应是在__init__里算好存起来,但那样对象一创建就付出代价,哪怕这次根本用不到。functools.cached_property就是为这个场景生的:第一次访问才算,算完存进实例,之后直接返回缓存。这篇讲清楚它怎么用、什么时候失效、以及一个容易忽略的线程安全坑。朴素写法的两个问题先看不加缓存的property:classReport:def__init__(self,path):self.pathpathpropertydefdata(self):print(正在解析...)# 每次访问都会打印withopen(self.path)asf:returnheavy_parse(f.read())# 每次都重新解析rReport(big.csv)print(r.data)# 正在解析...print(r.data)# 正在解析... —— 又算了一遍!property每次访问都执行方法体,重复计算。那放__init__里呢?classReport:def__init__(self,path):self.dataheavy_parse(open(path).read())# 创建对象就解析这又走向另一个极端:哪怕你只是想Report(big.csv).path,压根不用data,也被迫解析了一遍。我们想要的是「用到才算、算一次」。cached_property:惰性 缓存fromfunctoolsimportcached_propertyclassReport:def__init__(self,path):self.pathpathcached_propertydefdata(self):print(正在解析...)# 只会打印一次withopen(self.path)asf:returnheavy_parse(f.read())rReport(big.csv)print(r.data)# 正在解析... —— 第一次访问才计算print(r.data)# (无输出) —— 直接返回缓存它的原理很简单:第一次访问时执行方法,把结果写进实例的__dict__,属性名就叫data。之后再访问r.data,因为实例字典里已经有data了,描述符根本不会被触发,直接命中字典。你可以验证:print(datainr.__dict__)# 第一次访问后为 True,值就存这里怎么让缓存失效:直接 del正因为缓存存在实例__dict__里,想重新计算,del掉它就行:delr.data# 删掉缓存print(r.data)# 正在解析... —— 重新计算并再次缓存这比很多手写缓存方案干净:没有额外的_cache字段,失效就是删字典键。适合「数据源变了要刷新」的场景,比如文件被重写、配置被更新。和 property 的关键区别:cached_property 可以被赋值普通property不带 setter 时是只读的,赋值会报错。但cached_property因为本质是往实例字典写值,可以直接赋值覆盖:r.datamanual override# 合法!直接写进 __dict__print(r.data)# manual override这既是特性也是坑:如果你依赖data永远由计算得来,别人一行赋值就能悄悄改掉它。需要真正只读的语义时,用带缓存逻辑的普通 property 更稳。硬性限制:类必须有dictcached_property靠写实例__dict__工作,所以如果类定义了__slots__且没包含__dict__,它会直接报错:classReport:__slots__(path,)# 没有 __dict__cached_propertydefdata(self):return42Report(x).data# TypeError: No __dict__ attribute on Report ... cached_property用__slots__省内存的类想缓存属性,得手动实现,或者在 slots 里显式加上__dict__(但那样就抵消了 slots 的省内存效果)。最容易忽略的坑:不是线程安全的这是文档里写了但很多人没注意的点。多个线程同时第一次访问同一个实例的cached_property,计算函数可能被执行多次:importthreading,timefromfunctoolsimportcached_propertyclassConfig:cached_propertydefvalue(self):print(computing...)# 高并发下可能打印不止一次time.sleep(0.1)# 模拟慢计算,放大竞态return42cfgConfig()threads[threading.Thread(targetlambda:cfg.value)for_inrange(5)]fortinthreads:t.start()fortinthreads:t.join()# 可能看到多行 computing... —— 缓存写入前多个线程都在算Python 3.12 前的旧版本甚至用一把类级别的锁,导致不同实例的访问互相阻塞(性能问题);新版本移除了那把锁,于是变成上面这种「可能重复计算」。如果你的计算有副作用(比如建数据库连接)或者非常昂贵,别在多线程首次访问下裸用cached_property,自己加锁:importthreadingfromfunctoolsimportcached_propertyclassConfig:_lockthreading.Lock()cached_propertydefvalue(self):withself._lock:# 自己兜线程安全ifvalueinself.__dict__:returnself.__dict__[value]# 双重检查,别人已算好returnexpensive()好在大多数 Web 场景每个请求各用各的对象,单线程访问,裸用完全没问题。知道这个边界,才不会在高并发共享单例时被坑。小结cached_property 惰性计算 结果缓存进实例__dict__,第一次访问才算、之后直接命中。失效很简单:del obj.attr删掉缓存键即可重新计算。它可以被直接赋值覆盖(不像只读 property),既灵活也可能被误改。依赖实例__dict__,和不含__dict__的__slots__冲突。不是线程安全的:多线程首次并发访问可能重复执行计算,有副作用/昂贵计算时自己加锁。一句话记忆点:cached_property是「懒汉版属性」,单线程里用它省心又干净;一旦跨线程共享,记得它不帮你上锁。

相关新闻

万象生鲜分拣系统 PDA 多终端协同分拣技术拆解

万象生鲜分拣系统 PDA 多终端协同分拣技术拆解

万象生鲜分拣系统整合了PDA多终端联动分拣技术,它在提升分拣效率和降低错误率方面发挥了重要作用。该系统使得操作人员能够通过手持设备实时接收并确认订单,实现对货物的快速定位及处理。不同终端之间的信息共享确保了整个分拣过程的协调与顺畅&#xff…

2026/9/17 20:27:07 阅读更多 →
如何在开源项目中优雅推动性能优化?e18e社区的Advocacy沟通技巧

如何在开源项目中优雅推动性能优化?e18e社区的Advocacy沟通技巧

如何在开源项目中优雅推动性能优化?e18e社区的Advocacy沟通技巧 【免费下载链接】e18e 项目地址: https://gitcode.com/gh_mirrors/e1/e18e 开源项目性能优化并不只是写代码,更是一场需要技巧的沟通。e18e(Ecosystem Performance&…

2026/9/13 3:02:56 阅读更多 →
百度库库AI月活超1亿领跑AI办公,深入金融等专业场景挑战BAT格局!

百度库库AI月活超1亿领跑AI办公,深入金融等专业场景挑战BAT格局!

百度为什么先跑出来了?8月14日,百度文库、百度网盘在AI Day宣布,通用智能体GenFlow启用中文名库库AI,其月活超1亿,办公MAU超2500万。文库网盘1个月前组30人团队,20多天做出“库库AI”独立端。百度文库在《O…

2026/9/16 14:36:31 阅读更多 →

最新新闻

Keep 实战指南:三步接入开源 AIOps 告警管理,把响应时间压到 5 分钟

Keep 实战指南:三步接入开源 AIOps 告警管理,把响应时间压到 5 分钟

Keep 实战指南:三步接入开源 AIOps 告警管理,把响应时间压到 5 分钟 【免费下载链接】keep The open-source AIOps and alert management platform 项目地址: https://gitcode.com/GitHub_Trending/kee/keep 凌晨两点,第一条告警弹出&…

2026/9/19 3:21:27 阅读更多 →
ESP32-S2/S3 USB Host 多媒体流驱动 usb_stream 使用指南:UVC 摄像头与 UAC 音频的读、写与控制

ESP32-S2/S3 USB Host 多媒体流驱动 usb_stream 使用指南:UVC 摄像头与 UAC 音频的读、写与控制

ESP32-S2/S3 USB Host 多媒体流驱动 usb_stream 使用指南:UVC 摄像头与 UAC 音频的读、写与控制 【免费下载链接】esp-iot-solution Espressif IoT Library. IoT Device Drivers, Documentations and Solutions. 项目地址: https://gitcode.com/GitHub_Trending/e…

2026/9/19 3:21:27 阅读更多 →
5分钟装好的LibreHardwareMonitor完整指南:监控CPU温度、风扇与电压

5分钟装好的LibreHardwareMonitor完整指南:监控CPU温度、风扇与电压

5分钟装好的LibreHardwareMonitor完整指南:监控CPU温度、风扇与电压 【免费下载链接】LibreHardwareMonitor Libre Hardware Monitor is free software that can monitor the temperature sensors, fan speeds, voltages, load and clock speeds of your computer. …

2026/9/19 3:21:27 阅读更多 →
x64dbg DataTbyte 命令详解:将内存标记为 Tbyte(10 字节)数据类型

x64dbg DataTbyte 命令详解:将内存标记为 Tbyte(10 字节)数据类型

x64dbg DataTbyte 命令详解:将内存标记为 Tbyte(10 字节)数据类型 【免费下载链接】x64dbg An open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis. 项目地址: https://gitcode.com/gh_…

2026/9/19 3:21:27 阅读更多 →
Go高并发编程的终极武器:ants goroutine池完全指南,为什么大厂都在用

Go高并发编程的终极武器:ants goroutine池完全指南,为什么大厂都在用

Go高并发编程的终极武器:ants goroutine池完全指南,为什么大厂都在用 【免费下载链接】ants 🐜🐜🐜 ants is the most powerful and reliable pooling solution for Go. 项目地址: https://gitcode.com/gh_mirrors/a…

2026/9/19 3:21:27 阅读更多 →
Quixel Bridge与Megascans素材导入UE4完整指南:从安装到实战避坑

Quixel Bridge与Megascans素材导入UE4完整指南:从安装到实战避坑

做场景做到一半,最容易让人泄气的事情之一就是:模型、贴图、植被这些素材永远不够用。自己做材质,调参数动辄半天,外包买资源又是一笔预算,最后往往卡在“不是不会做,而是没东西可做”的尴尬位置上。Quixel…

2026/9/19 3:20:26 阅读更多 →

日新闻

BP神经网络时序预测:滑窗长度与多窗口平均策略

BP神经网络时序预测:滑窗长度与多窗口平均策略

简介:面向机器学习、深度学习与数据建模学习者的一份完整研究文献,聚焦BP神经网络在农业产量预测中的应用。文档以1980—2018年全国棉花产量为样本,系统讲解数据归一化处理、激活函数原理、多层神经网络结构搭建及训练流程,展示敏…

2026/9/19 0:00:30 阅读更多 →
Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

上个月调一个Deformable DETR模型,在单卡上要跑将近两天。第二天早上我下意识打开终端翻日志,发现loss从凌晨两点就开始往上爬,一路从0.8涨到1.35,整整六个小时没人发现。那六个小时的训练不仅白跑,还霸占着卡——等于…

2026/9/19 0:00:30 阅读更多 →
OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南 【免费下载链接】opencloud 🌤️ OpenCloud is the open source platform for file management, sharing and collaboration. Simple and sovereign. 项目地址: htt…

2026/9/19 0:00:30 阅读更多 →

周新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/16 19:03:19 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/17 7:57:36 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/17 10:19:14 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/16 22:31:27 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/15 21:39:18 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/16 22:32:59 阅读更多 →