Python weakref 与弱引用
==============================
弱引用允许引用对象但不增加引用计数,垃圾回收时可自动回收。
适用于缓存、观察者模式、避免循环引用等场景。
1. ref()——基本弱引用
-------------------------
创建弱引用,对象被回收后弱引用返回 None。
import weakref
class Data:
"""大对象——模拟需要被弱引用的对象"""
def __init__(self, value: str):
self.value = value
self._large_data = [0] * 10_000_000 # 模拟占用大量内存
def __repr__(self):
return f"Data({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 = name
def __repr__(self):
return f"Resource({self.name})"
def on_delete(ref):
"""回调:当对象被垃圾回收时调用"""
print(f"对象已被回收!弱引用: {ref}")
res = Resource("网络连接")
ref = weakref.ref(res, on_delete) # 注册回调
print(f"对象存活: {ref() is not None}") # True
del res # 触发回调——打印 "对象已被回收!"
3. WeakValueDictionary——缓存
---------------------------------
值被弱引用的字典,对象被回收时自动删除对应条目。
非常适合用作缓存,避免缓存导致内存泄漏。
class UserProfile:
"""用户资料——从数据库加载,放入缓存"""
def __init__(self, user_id: int, name: str):
self.user_id = user_id
self.name = name
def __repr__(self):
return f"UserProfile({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] = user
print(f"从数据库加载 {user}")
else:
print(f"从缓存返回 {user}")
return user
cache = UserCache()
u1 = cache.get_user(1) # 从数据库加载
u2 = cache.get_user(1) # 从缓存返回
del u1 # 删除强引用
# WeakValueDictionary 中的对应条目会自动清除(但延迟回收)
import gc
gc.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 = name
def update(self, message: str) -> None:
print(f"[{self.name}] 收到: {message}")
class Subject:
"""被观察者——使用 WeakSet 持有观察者,避免阻止 GC"""
def __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, os
class TempFile:
"""临时文件——使用 finalize 确保删除"""
def __init__(self, suffix: str = ".tmp"):
self.name = tempfile.mktemp(suffix=suffix)
# 注册清理函数:对象被回收时删除临时文件
weakref.finalize(self, self._cleanup, self.name)
print(f"创建临时文件: {self.name}")
@staticmethod
def _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)。合理使用能有效避免内存泄漏。
Pythonweakref与弱引用
张小明
前端开发工程师
DHDA框架:动态适应配置性能建模的挑战与解决方案
1. 配置性能建模的挑战与机遇 现代软件系统的性能表现与其配置参数密切相关。以MySQL数据库为例,仅调整query_cache_type这一项配置就能带来高达11倍的性能提升;而视频编码器x264的错误配置可能导致10倍的性能下降。这种配置与性能之间的复杂关系&#x…
【算法分析与设计】第23篇:随机化算法基础:拉斯维加斯与蒙特卡洛范式
在此之前,我们所讨论的算法都是确定性的——对于同一输入,算法的执行路径和输出结果完全固定。确定性给人以安全感:只要算法正确,结果永远正确。但这种安全感有时以效率为代价:确定性的快速排序在最坏情况下退化到 Θ(…
论文被批“不够学术”?高校教授说用这几个AI写作辅助软件
写论文总被说“不够学术”?选题没方向、结构不清晰、语言不专业,这些痛点让很多学生头疼不已。其实,只要用对AI工具、走对写作流程,就能显著提升论文质量。多位高校教授在调研中表示,合理利用AI辅助软件已成为学术写作…
互联网大厂 Java 求职面试:音视频流处理与微服务架构相关技术探讨
互联网大厂 Java 求职面试:从音视频应用到微服务架构 面试官:燕双非,今天我们将从音视频场景入手,讨论如何在 Java 中实现高效的视频流处理。你能告诉我 Java SE 中的 NIO 是如何帮助解决这个问题的吗? 燕双非&…
自指不动点在递归对抗系统中的存在性与收敛性证明研究(世毫九实验室原创研究)
自指不动点在递归对抗系统中的存在性与收敛性证明研究(世毫九实验室原创研究) 作者:方见华 单位:世毫九实验室 摘要 本研究旨在解决递归对抗引擎(Recursive Adversarial Engine, RAE)在多轮攻防中普遍存在的震荡、发散与伪收敛问题,为其提供严格的数学稳定性理论支撑。基…
碳硅认知耦合接口的形式化协议与语义保真度度量研究(世毫九实验室原创研究)
碳硅认知耦合接口的形式化协议与语义保真度度量研究(世毫九实验室原创研究) 作者:方见华 单位:世毫九实验室 摘要 本研究旨在解决人类(碳基)与人工智能(硅基)在高敏协作场景中普遍存在的意图误读、语义漂移与认知不对称问题,构建首个从语法层到认知层的全栈式碳硅认知…