python中weakref模块通过弱引用机制打破循环引用以防止内存泄漏,具体包括:一、weakref.ref创建不增加引用计数的可调用弱引用;二、weakkeydictionary使键对象销毁后自动移除对应项;三、weakvaluedictionary使值对象销毁后自动失效对应条目;四、在回调中用weakref.ref避免闭包强持有对象;五、weakref.finalize注册对象销毁前的清理回调。

在 Python 中,当对象之间存在循环引用时,垃圾回收器可能无法及时释放内存,导致内存泄漏。weakref 模块提供弱引用机制,使对象可以在不增加引用计数的前提下被访问,从而打破循环引用。以下是使用 weakref 避免内存泄漏的具体方法:
一、使用 weakref.ref 创建弱引用
weakref.ref 返回一个可调用对象,该对象在目标对象未被销毁时返回目标对象,否则返回 None。它不参与引用计数,因此不会阻止目标对象被回收。
1、导入 weakref 模块:import weakref
2、定义一个类并创建实例:class DataHolder: pass; obj = DataHolder()
立即学习“Python免费学习笔记(深入)”;
3、创建弱引用:ref_obj = weakref.ref(obj)
4、通过调用弱引用对象获取原对象:target = ref_obj()(若 target 为 None,说明原对象已被回收)
二、使用 weakref.WeakKeyDictionary 存储以对象为键的映射
WeakKeyDictionary 的键是弱引用,当键对象被销毁后,对应键值对自动从字典中移除,避免因字典长期持有所致的内存滞留。
1、创建 WeakKeyDictionary 实例:cache = weakref.WeakKeyDictionary()
2、将对象作为键存入:holder = DataHolder(); cache[holder] = "metadata"
3、删除 holder 引用后再次访问 cache,len(cache) 将变为 0
三、使用 weakref.WeakValueDictionary 存储以对象为值的映射
WeakValueDictionary 的值是弱引用,当值对象被销毁时,对应条目自动失效,适用于缓存场景中避免值对象长期驻留内存。
1、创建 WeakValueDictionary 实例:pool = weakref.WeakValueDictionary()
2、插入键值对:key_obj = DataHolder(); pool["key"] = key_obj
3、删除 key_obj 的强引用后,pool["key"] 将引发 KeyError
四、在回调函数中使用 weakref.ref 防止闭包持有对象
当为对象注册回调(如事件监听器)时,若回调函数直接引用对象,会形成循环引用。使用 weakref.ref 可解耦生命周期依赖。
1、定义带回调的类:class EventSource: def __init__(self): self.callbacks = []
2、注册弱引用回调:def callback_ref(): ref = weakref.ref(self); return lambda: ref() and ref().on_event()
3、将回调加入列表:self.callbacks.append(callback_ref())
五、使用 weakref.finalize 注册对象销毁时的清理逻辑
finalize 允许为对象注册一个在对象被销毁前执行的回调,无需手动管理生命周期,适合资源释放或日志记录。
1、创建需监控的对象:resource = open("temp.txt", "w")
2、注册终结器:finalizer = weakref.finalize(resource, lambda f: f.close() if not f.closed else None)
3、显式删除 resource 引用:del resource,随后 finalize 回调将被执行










