Python 中弱引用的神奇用法与原理探析

python:weakref --- 弱引用 阅读详情

Python 中弱引用的神奇用法与原理探析

弱引用可以在不产生引用计数的前提下,对目标对象进行管理,常用于框架和中间件中。弱引用看起来很神奇,其实设计原理是非常简单的观察者模式。

作者:佚名来源:Python开发者|2021-12-09 15:45

 收藏

  分享

 背景

开始讨论弱引用( weakref )之前,我们先来看看什么是弱引用?它到底有什么作用?

假设我们有一个多线程程序,并发处理应用数据:

 
  1. # 占用大量资源,创建销毁成本很高  
  2. class Data:  
  3.     def __init__(self, key):  
  4.         pass 

应用数据 Data 由一个 key 唯一标识,同一个数据可能被多个线程同时访问。由于 Data 需要占用很多系统资源,创建和消费的成本很高。我们希望 Data 在程序中只维护一个副本,就算被多个线程同时访问,也不想重复创建。

为此,我们尝试设计一个缓存中间件 Cacher :

 
  1. import threading  
  2. # 数据缓存  
  3. class Cacher:  
  4.     def __init__(self):  
  5.         self.pool = {}  
  6.         self.lock = threading.Lock()  
  7.     def get(self, key):  
  8.         with self.lock:  
  9.             data = self.pool.get(key)  
  10.             if data:  
  11.                 return data  
  12.             self.pool[key] = data = Data(key)  
  13.             return data 

Cacher 内部用一个 dict 对象来缓存已创建的 Data 副本,并提供 get 方法用于获取应用数据 Data 。get 方法获取数据时先查缓存字典,如果数据已存在,便直接将其返回;如果数据不存在,则创建一个并保存到字典中。因此,数据首次被创建后就进入缓存字典,后续如有其它线程同时访问,使用的都是缓存中的同一个副本。

感觉非常不错!但美中不足的是:Cacher 有资源泄露的风险!

因为 Data 一旦被创建后,就保存在缓存字典中,永远都不会释放!换句话讲,程序的资源比如内存,会不断地增长,最终很有可能会爆掉。因此,我们希望一个数据等所有线程都不再访问后,能够自动释放。

我们可以在 Cacher 中维护数据的引用次数, get 方法自动累加这个计数。于此同时提供一个 remove 新方法用于释放数据,它先自减引用次数,并在引用次数降为零时将数据从缓存字段中删除。

线程调用 get 方法获取数据,数据用完后需要调用 remove 方法将其释放。Cacher 相当于自己也实现了一遍引用计数法,这也太麻烦了吧!Python 不是内置了垃圾回收机制吗?为什么应用程序还需要自行实现呢?

冲突的主要症结在于 Cacher 的缓存字典:它作为一个中间件,本身并不使用数据对象,因此理论上不应该对数据产生引用。那有什么黑科技能够在不产生引用的前提下,找到目标对象吗?我们知道,赋值都是会产生引用的!

典型用法

这时,弱引用( weakref )隆重登场了!弱引用是一种特殊的对象,能够在不产生引用的前提下,关联目标对象。

 
  1. # 创建一个
深入CPython内核:从对象模型到内存管理,掌握Python底层原理 在编程语言中,内存管理与对象模型是理解语言运行机制的核心基础。CPython作为Python的官方实现,其内部采用引用计数与分代垃圾回收相结合的内存管理策略,确保了内存的高效分配与回收。这种机制不仅直接关系到程序的性能表现,更是理解Python‘万物皆对象’哲学的技术基石。通过剖析PyObject结构体,可以揭示动态类型、引用语义等高级特性的底层实现原理。掌握这些底层知识,对于进行高性能计算、开发C扩展模块、优化内存使用以及调试复杂问题具有重要价值。本文聚焦于CPython内核中对象模型与内存管理这两个关键 阅读详情

相关推荐

Frida源码解析:JavaScript在Native进程中的运行机制与跨语言交互设计

动态插桩是现代软件分析、安全测试和逆向工程中的关键技术,它允许在程序运行时注入并执行自定义代码,实现对目标进程行为的监控与修改。其核心原理在于通过进程注入、API Hook和内存操作等技术,在非JavaScript环境中安全地引入并管理一个脚本运行时。这项技术的价值在于为安全研究人员和开发者提供了强大的动态分析能力,广泛应用于移动应用安全评估、漏洞挖掘、协议分析和自动化测试等场景。以Frida为例,它通过精巧的架构设计,在目标进程内构建了一座连接Native代码与JavaScript的桥梁,其JavaScr

xpp02的专栏 411

C++与Lua集成实战:热更新与行为定义系统构建指南

在软件工程中,脚本语言与编译型语言的结合是提升系统灵活性与开发效率的常见架构模式。其核心原理在于通过清晰的接口定义与数据交换机制,让高性能的底层框架与动态的上层逻辑协同工作。这种架构的技术价值在于实现了关注点分离:底层负责性能密集型任务,上层专注于业务逻辑快速迭代。在游戏开发、工业仿真等需要频繁调整规则和内容的领域,这种模式尤其重要。通过引入热更新机制,系统可以在不重启主程序的情况下替换脚本逻辑,极大地缩短了调试和部署周期。同时,行为定义系统允许非程序员通过脚本参与内容创作,进一步解放了生产力。本文以C++

weixin_33874713的博客 326

01-FreeSWITCH 的安装、部署、配置以及可能遇到的问题和解决方法

一文让您了解从FreeSWITCH 的安装、部署、配置、可能遇到的问题及解决方法。一切从实际项目出发,以工程应用为目的。

秋风的博客 2127

基于FPGA的DDS信号发生器

之前的博客讲到了DDS的基本原理,现在用Verilog代码实现DDS,能够产生四种波形,方波,三角波,正弦波,锯齿波,用按键来控制频率和选择波形。其中按键消抖模块来自小梅哥的FPGA自学笔记设计与验证这本书。 module DDS_Module( Clk, Rst_n, EN, Fword, Key1, Pword, DA_Clk, DA_Data ); input Clk...

qq_43534451的博客 9946

告别双导航栏!微信小程序web-view嵌入H5的导航栏隐藏实战(附uniapp代码)

本文详细解析了微信小程序中web-view嵌入H5页面时出现的双导航栏问题,并提供了基于uniapp的完整解决方案。通过环境感知、动态适配和样式隔离等技术手段,实现导航栏的无缝整合,提升用户体验和屏幕空间利用率。文章包含实战代码示例和常见问题排查指南,帮助开发者快速解决这一常见痛点。

weixin_26945061的博客 342

自定义模型训练——打造专属OpenClaw模型(2026AI版)

本文介绍了OpenClaw自定义模型训练的核心流程,包括框架选择(PyTorch、TensorFlow、HuggingFace和原生OpenClaw框架)、训练环境搭建脚本、以及数据收集系统的设计。数据收集器支持从数据库、API、文件和网络等多种来源获取训练数据,并提供灵活的过滤机制确保数据质量。通过这套系统,开发者可以高效准备训练数据,为后续模型训练打下坚实基础。

博客 874

STM32 IIC电量计LTC2944

LTC2944是一款电池电量计,设计用于端电压为3.6V至60V的多节电池。它测量电池充电和放电、电池电压、电流和自身温度。精密模拟库仑计数器通过电池正极端子与负载或充电器之间的检测电阻器对电流进行积分。电池电压、电池电流和硅温度由内部ADC测量。

baidu_34971492的博客 3160

python批量调用大模型API:多线程和异步协程

本文介绍了利用多线程技术批量调用大模型API的实现方法。核心是通过并发请求提高处理效率,主要采用线程池管理并发数量、结果聚合等技术。文章提供了一个完整的Python实现示例,包含APIBatchCaller类及其single_api_call和batch_call方法,详细解析了并发控制、错误处理等关键点,并给出了使用注意事项,包括并发数设置、重试策略和超时处理等。该方案特别适合IO密集型任务,能显著提升批量API调用的效率。

Cachel Wood的博客 759

系统建模语言 (SysML)

系统建模语言

追赶时代的博客 749

一文吃透 Tools for Applying SAP Notes:从 SNOTE、TCI 到 Solution Manager 与 SAP Cloud ALM

本文系统梳理了SAP技术与运维团队应用SAP Notes的高效工具与方法,涵盖On-Premise与云环境。文章首先阐述了精研SAP Notes工具的必要性,指出其是实施错误修复、法务变更和性能改进的关键载体。随后详细介绍了SNOTE、TCI、Solution Manager、Cloud ALM和Maintenance Planner等核心工具的定位与适用场景,并通过采购异常案例展示了标准更正流程。针对复杂修复场景,文章提出了TCI的批量处理方案,并强调将Note实施纳入变更治理流程的重要性。最后总结了三种

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 346

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

上一篇: 超有趣的 Python 开源工具,教你做出彩色、会动的二维码
下一篇: Python 的十大特性
Python_xiaowu
博客等级 码龄5年 3096粉丝 178原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值