当前位置: 首页 > news >正文

Pythonweakref与弱引用

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)。合理使用能有效避免内存泄漏。

http://www.rkmt.cn/news/1422986.html

相关文章:

  • Lindy智能灌溉控制器深度拆解(固件漏洞/通信协议/边缘逻辑全曝光)
  • 别再傻傻分不清!工业自动化里零线和地线接错有多危险?附安全接线实操
  • ​ 带标注的番茄西红柿疾病检测数据集,可识别健康和8种常见疾病的叶子,识别率99.1%,8226张图,支持yolo,coco json,voc xml,文末有模型训练代码
  • Pythonuuid与唯一标识
  • 当微信聊天记录成为数字遗产:一个开源项目的警示与思考
  • Iterative BC-Max:用离线模仿学习优化编译器函数内联决策
  • Keil MDK多目标配置导致文件重复显示的解决方案
  • iStore终极指南:5分钟掌握OpenWRT应用商店的完整使用方法
  • 用数据说话!盘点2026年冠绝行业的的AI论文网站
  • Anthropic完成650亿美元H轮融资,估值达9650亿美元,多家巨头助力算力扩张
  • 口碑爆棚!专攻临床内科主任医师考试的好老师推荐! - 医考机构品牌测评专家
  • 为什么92%的内容团队还在手动运营?Lindy自动化工作流的7个致命断点与修复清单(内部泄露版)
  • PythonTrie前缀树实现
  • 基于图像识别的游戏自动化架构深度解析:E7Helper技术实现原理与设计哲学
  • 2026上海App软件开发公司TOP10推荐,一线大厂与实力派企业全解析
  • 如何为OBS Studio搭建专业级无线视频传输系统:DistroAV完全指南
  • 2026年最受好评的高温含硅脱模剂品牌推荐 - 企业推荐官【官方】
  • 从零开始:互联网大厂 Java 求职者面试之旅——技术栈与场景分析
  • 第九篇:《Dockerfile 指令精讲(二):WORKDIR、ENV、ARG、EXPOSE》
  • 深度解析黄金回收定价逻辑,乌鲁木齐黄金回收首选永盛黄金首饰店 - 企业推荐官【官方】
  • 023、YOLOv6 EfficientRep 重参数化 backbone 原理解析与训练-部署两阶段策略
  • WechatExporter深度解析:从iTunes备份到聊天记录导出的技术实现
  • 论文被批“不够学术”?高校教授说用这几个AI写作辅助软件
  • 3分钟掌握:B站缓存视频无损转换的智能方案
  • 2026论文隐藏级降AIGC工具大曝光:三步直降AIGC率至安全阈值!
  • Java开发者面试:从电商场景到微服务架构的深入探讨
  • 树莓派摄像头实时视频流服务器搭建:Flask+PiCamera实战指南
  • 手把手调参:解决IMU倾斜安装导致的车载组合导航漂移问题(附Python验证代码)
  • 给编程者的微积分课:用Python可视化理解函数连续、可导与洛必达法则
  • 保姆级教程:在 Qt 中为你的点云显示窗口添加鼠标交互(旋转/平移/缩放)与网格坐标轴