弱引用不增加引用计数,可被垃圾回收,用于避免循环引用和内存泄漏;通过weakref.ref()创建弱引用,WeakKeyDictionary和WeakValueDictionary实现自动清理的映射,WeakMethod用于安全绑定回调,适用于缓存、事件监听等场景。

掌握 Python 中 weakref 模块的关键在于理解弱引用与普通引用的区别,以及它在避免循环引用和节省内存方面的实际用途。弱引用不会增加对象的引用计数,因此不会阻止对象被垃圾回收。这在缓存、观察者模式或树形结构中特别有用。
什么是弱引用?
Python 默认使用强引用:只要有一个变量指向对象,该对象就不会被销毁。而弱引用允许你指向一个对象,但不阻止它被回收。
使用 weakref 创建的引用,在原对象被删除后会自动失效。
常见场景:- 缓存大量对象时,不想因为引用导致内存无法释放
- 父子对象互相引用,避免循环引用导致内存泄漏
- 实现回调机制或事件监听器,避免“僵尸”监听器占用内存
基本用法:创建弱引用
使用 weakref.ref() 可以创建一个弱引用对象。调用这个引用时返回原始对象,如果对象已被回收,则返回 None。
立即学习“Python免费学习笔记(深入)”;
示例:import weakrefclass MyClass: def init(self, name): self.name = name def del(self): print(f"{self.name} 被删除")
obj = MyClass("test") wref = weakref.ref(obj)
print(wref()) # 输出: <main.MyClass object at 0x...> del obj # 删除强引用,触发 del print(wref()) # 输出: None
常用工具类:WeakKeyDictionary 和 WeakValueDictionary
这两个容器是 weakref 模块中最实用的部分,适合用于映射关系且不希望影响对象生命周期。
WeakKeyDictionary:- 键必须是可弱引用的(通常是实例)
- 当某个键对象被回收,对应的条目会自动从字典中删除
- 适合用于给对象动态附加数据而不影响其生命周期
WeakValueDictionary:
- 值是弱引用
- 当值对象被回收,对应键值对自动清除
- 常用于实现缓存
示例:使用 WeakValueDictionary 做缓存
import weakrefcache = weakref.WeakValueDictionary()
class CachedObject: def init(self, name): self.name = name
def get_object(name): obj = cache.get(name) if obj is None: obj = CachedObject(name) cache[name] = obj print(f"创建新对象: {name}") return obj
a = get_object("A") b = get_object("B") c = get_object("A") # 应该命中缓存 print(a is c) # True
del a, c
此时 "A" 的对象可能被回收
d = get_object("A") # 会重新创建 print(d.name) # 创建新对象: A
绑定方法和回调:使用 weakref.WeakMethod
如果你需要弱引用一个对象的方法(比如注册回调),直接用 ref 会保留整个实例,导致无法回收。这时应该用 WeakMethod。
示例:import weakrefclass Listener: def on_event(self): print("收到事件")
listener = Listener() callback = weakref.WeakMethod(listener.on_event)
method_ref = callback() if method_ref: method_ref() # 调用方法
del listener method_ref = callback() # 现在为 None
基本上就这些。理解 weakref 的核心是意识到“我不拥有这个对象”。只要不用强引用,配合 WeakValueDictionary 或 WeakMethod 使用,就能有效管理内存。不复杂但容易忽略。











