
Python weakref 与弱引用弱引用允许引用对象但不增加引用计数垃圾回收时可自动回收。适用于缓存、观察者模式、避免循环引用等场景。1. ref()——基本弱引用-------------------------创建弱引用对象被回收后弱引用返回 None。import weakrefclass Data:大对象——模拟需要被弱引用的对象def __init__(self, value: str):self.value valueself._large_data [0] * 10_000_000 # 模拟占用大量内存def __repr__(self):return fData({self.value})obj Data(重要的数据)ref weakref.ref(obj) # 创建弱引用print(ref()) # Data(重要的数据)——通过弱引用访问原对象print(ref() is obj) # True——是同一个对象del obj # 删除原对象唯一强引用print(ref()) # None——对象已被回收2. ref() 回调通知---------------------当被引用对象被回收时回调函数被触发。class Resource:资源类——回收时通知def __init__(self, name: str):self.name namedef __repr__(self):return fResource({self.name})def on_delete(ref):回调当对象被垃圾回收时调用print(f对象已被回收弱引用: {ref})res Resource(网络连接)ref weakref.ref(res, on_delete) # 注册回调print(f对象存活: {ref() is not None}) # Truedel res # 触发回调——打印 对象已被回收3. WeakValueDictionary——缓存---------------------------------值被弱引用的字典对象被回收时自动删除对应条目。非常适合用作缓存避免缓存导致内存泄漏。class UserProfile:用户资料——从数据库加载放入缓存def __init__(self, user_id: int, name: str):self.user_id user_idself.name namedef __repr__(self):return fUserProfile({self.name})class UserCache:用户缓存——使用 WeakValueDictionary 自动管理def __init__(self):self._cache weakref.WeakValueDictionary() # 值被弱引用def get_user(self, user_id: int) - UserProfile | None:从缓存获取用户缓存未命中时加载user self._cache.get(user_id)if user is None:# 模拟从数据库加载user UserProfile(user_id, f用户{user_id})self._cache[user_id] userprint(f从数据库加载 {user})else:print(f从缓存返回 {user})return usercache UserCache()u1 cache.get_user(1) # 从数据库加载u2 cache.get_user(1) # 从缓存返回del u1 # 删除强引用# WeakValueDictionary 中的对应条目会自动清除但延迟回收import gcgc.collect() # 强制垃圾回收print(cache._cache) # 可能只剩下部分条目4. WeakKeyDictionary——元数据----------------------------------键被弱引用的字典用于为对象附加元数据而不影响其生命周期。class Widget:界面组件def __init__(self, name: str):self.name name# 为 Widget 对象附加工具提示信息但不影响其生命周期tooltips weakref.WeakKeyDictionary()w1 Widget(按钮)w2 Widget(输入框)tooltips[w1] 点击此处提交tooltips[w2] 在此输入文本print(tooltips[w1]) # 点击此处提交del w1 # 删除 Widget 对象print(len(tooltips)) # 1——w1 的条目自动清除5. WeakSet——弱引用集合---------------------------集合中的元素被弱引用适合观察者模式。class Observer:观察者def __init__(self, name: str):self.name namedef update(self, message: str) - None:print(f[{self.name}] 收到: {message})class Subject:被观察者——使用 WeakSet 持有观察者避免阻止 GCdef __init__(self):self._observers weakref.WeakSet() # 观察者被弱引用def attach(self, observer: Observer) - None:self._observers.add(observer)def notify(self, message: str) - None:for obs in self._observers:obs.update(message)subject Subject()obs1 Observer(观察者A)obs2 Observer(观察者B)subject.attach(obs1)subject.attach(obs2)subject.notify(事件触发) # 两个观察者都收到del obs1 # 观察者A 被回收subject.notify(第二次事件) # 只有观察者B 收到6. finalize——资源清理-------------------------注册对象回收时的清理函数比 __del__ 更可靠。import tempfile, osclass TempFile:临时文件——使用 finalize 确保删除def __init__(self, suffix: str .tmp):self.name tempfile.mktemp(suffixsuffix)# 注册清理函数对象被回收时删除临时文件weakref.finalize(self, self._cleanup, self.name)print(f创建临时文件: {self.name})staticmethoddef _cleanup(path: str) - None:静态清理函数不绑定到实例if os.path.exists(path):os.remove(path)print(f删除临时文件: {path})def read(self) - str:with open(self.name, r) as f:return f.read()def process_temp():tf TempFile()print(tf.read()) # 使用临时文件# 函数结束时 tf 被回收触发 finalize 清理7. proxy——代理对象----------------------proxy 行为像原对象的透明代理但不需要调用 ref()。class Service:def request(self) - str:return 服务响应svc Service()proxy weakref.proxy(svc) # 创建透明代理print(proxy.request()) # 服务响应——无需调用 ()svc.request is proxy.request # True——方法也相同del svc# print(proxy.request()) # ReferenceError: weakly-referenced object no longer exists总结weakref 提供了不增加引用计数的对象引用方式用于缓存WeakValueDictionary、元数据管理WeakKeyDictionary、观察者模式WeakSet和资源清理finalize。合理使用能有效避免内存泄漏。