0

0

weakref 如何正确使用来避免循环引用导致内存泄漏

舞姬之光

舞姬之光

发布时间:2026-01-22 20:20:01

|

341人浏览过

|

来源于php中文网

原创

weakref 的核心用途是打破循环引用以防内存泄漏,即不持有强引用而仅临时获取对象,允许其被及时销毁;典型应用是在子对象对父对象的反向引用中使用 weakref.ref,并每次调用后检查是否为 None。

weakref 如何正确使用来避免循环引用导致内存泄漏

在 Python 中,weakref 的核心用途之一就是打破循环引用,防止对象无法被垃圾回收(GC),从而避免内存泄漏。关键在于:**不持有强引用,只在需要时临时获取对象,且允许对象在无其他强引用时被及时销毁。**

理解循环引用为何导致泄漏

Python 主要靠引用计数 + 周期性 GC 清理循环引用。但若两个对象互相持强引用(如父对象存子列表,子对象又存父引用),即使外部不再使用它们,引用计数也不为 0,只能依赖 GC。而 GC 并非实时触发,尤其在 CPython 中,某些场景(如含 __del__ 方法的对象)可能完全不被 GC 处理,造成泄漏。

例如:

class Parent:
    def __init__(self):
        self.children = []
<p>class Child:
def <strong>init</strong>(self, parent):
self.parent = parent  # 强引用父对象
parent.children.append(self)</p><p>p = Parent()
c = Child(p)  # p ↔ c 形成循环引用
del p, c  # 对象仍驻留内存,可能不被回收

用 weakref 替代强引用的关键位置

应在“从属方”对“主控方”的反向引用处使用 weakref,即子对象引用父对象、缓存引用目标、回调中保存对象等场景。

AssemblyAI
AssemblyAI

转录和理解语音的AI模型

下载
  • weakref.ref 包装父对象,调用时加 () 获取(可能返回 None
  • weakref.WeakKeyDictionaryWeakValueDictionary 管理映射关系,键或值被销毁时自动清理条目
  • 避免在 __del__ 中访问 weakref 对象(此时对象可能已部分析构)

典型安全写法示例

修正上面的父子关系:

import weakref
<p>class Parent:
def <strong>init</strong>(self):
self.children = []</p><p>class Child:
def <strong>init</strong>(self, parent):
self._parent_ref = weakref.ref(parent)  # 弱引用
parent.children.append(self)</p><pre class="brush:php;toolbar:false;">@property
def parent(self):
    return self._parent_ref()  # 调用 ref 对象获取实例,可能为 None

p = Parent() c = Child(p) print(c.parent is p) # True del p print(c.parent) # None — 安全,不崩溃

注意:self._parent_ref() 是动态取值,不是缓存强引用;每次使用都应检查是否为 None

其他实用 weakref 工具与注意事项

weakref.finalize 可注册对象销毁时的清理逻辑,比 __del__ 更可靠;weakref.WeakSet 适合管理一组可随时消失的对象。

  • 不要对不可弱引用类型(如 int、str、tuple)创建 weakref,会报 TypeError
  • 避免长期持有 weakref.ref 实例本身(它自己也是对象),若 ref 对象还活着,目标对象无法被回收
  • 多线程中使用 weakref 是安全的,但访问解引用结果仍需自行同步

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
python中print函数的用法
python中print函数的用法

python中print函数的语法是“print(value1, value2, ..., sep=' ', end=' ', file=sys.stdout, flush=False)”。本专题为大家提供print相关的文章、下载、课程内容,供大家免费下载体验。

193

2023.09.27

python print用法与作用
python print用法与作用

本专题整合了python print的用法、作用、函数功能相关内容,阅读专题下面的文章了解更多详细教程。

19

2026.02.03

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1051

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

615

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

335

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

235

2025.08.29

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

766

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

377

2025.12.24

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号