Python 垃圾回收和弱引用(Weakref)

Python中的赋值语句是建立变量名与对象的引用关系,多个变量可以引用同一个对象,当对象的引用数归零时,可能会被当作垃圾回收。而弱引用即可以引用对象,又不会阻止对象被当作垃圾回收,因此这个特性非常适合用在缓存场景,当对象被当作垃圾回收时,其缓存信息会同步清除。

文章目录

  • 一、对象引用与垃圾回收
  • 二、弱引用/weakref模块
    • 2.1 weakref.ref 弱引用函数
    • 2.2 weakref.proxy 弱引用代理
    • 2.3 weakref.WeakValueDictionary 弱引用字典
    • 2.4 weakref.finalize 终结器
  • 三、弱引用的局限性

一、对象引用与垃圾回收

Python中的赋值语句不是创造对象而是建立引用关系,执行一个赋值语句时,如果对象不存在,则会先创建对象,然后建立变量与对象的引用关系。

下面赋值语句中,Python会先创建集合对象,让后建立变量名set1与对象的引用关系:

set1 = {1, 2, 3}

在这里插入图片描述

此时执行 set2 = set1,不会建立新的对象,而是建立变量名set2到集合对象的引用关系:
在这里插入图片描述

同样,del语句不是删除对象,而是删除引用关系,del set1只是删除了set1到集合对象的引用,而set2的引用依然存在,所以对象并不会被销毁:

del set1

在这里插入图片描述
每个对象都会统计有多少个引用指向自己,正是因为有引用对象才会存在。当对象的引用计数归零后,垃圾回收程序会将对象销毁并释放内存。

二、弱引用/weakref模块

所谓弱引用就是引用对象但是不增加引用计数,即弱引用关系不会妨碍对象被当做垃圾回收,但在实际销毁对象前,弱引用也能返回该对象。这种特性经常用在缓存场景,当对象在程序的其他地方被当垃圾回收后,缓存中对象也会自动删除。python中的weakref模块可以创建对象的弱引用。

2.1 weakref.ref 弱引用函数

weak.ref(object[, callback])创建对象的弱引用。可以通过调用weakref.ref的返回对象来获取其引用的内容,如果弱引用的对象还存在则返回引用对象,若不存在则返回None。若提供了回调函数callback,则在对象即将销毁时将调用回调函数,引用对象将作为回调函数的唯一参数,随后对象销毁。

示例:建立变量set1到集合{1, 2, 3}的弱引用,同时自定回调函数func,在对象销毁时打印"Object is gone!"提示我们:

def func(self):    #  自定义回调函数print("Object is gone!")import weakref
set1 = {1, 2, 3}
wref = weakref.ref(set1, func)    # 建立弱引用关系

在这里插入图片描述

调用wref()可以获得其引用的对象:

wref()   

在这里插入图片描述

将变量名set1引用至其他对象,原集合对象引用计数归零将被销毁,同时打印了提示信息。通过再次调用wref()可以确定其引用对象已被销毁(返回None):

set = 1
wref()

在这里插入图片描述

2.2 weakref.proxy 弱引用代理

weakref.proxy(object[, callback])创建一个弱引用的对象代理,代理不需要调用即可访问原对象内容:

import weakref
set1 = {1, 2, 3}
wref = weakref.proxy(set1) 

在这里插入图片描述

2.3 weakref.WeakValueDictionary 弱引用字典

WeakValueDictionary 是一个字典类,里面的值是对象的弱引用。当被引用的对象在程序的其他地方被当作垃圾回收后,对应的键会自动从 WeakValueDictionary 中删除,因此非常适合用于缓存。

示例:假设程序中定义了一个类person用于存储姓名和工资信息,details保存了该类的2个实例:

class person:def __init__(self,name, salary):self.name = nameself.salary = salarydef __repr__(self):return 'Name:{} => Salary:{}.format(self.name, self.salary)'details = [person('Vincent', 1000), person('Victor', 2000)]

在这里插入图片描述

在缓存中,可以定义一个弱引用字典来保存details中的内容:

weakdetails = weakref.WeakValueDictionary()
for detail in details:weakdetails[detail.name] = detail    # 建立实例和名称的弱引用

在这里插入图片描述

通过weakdetails.keys()可以看到其也引用了2个实例,假设程序中执行了del details[0] 将vincent的实例删除,再次调用weakdetails.keys()即可看到其中的键也自动删除了:

sorted(weakdetails.keys())
del details[0]    # 删除detials中的vincent实例
sorted(weakdetails.keys())    # weakdetails中的引用关系也同步删除了

在这里插入图片描述
和WeakValueDictionary对应的还有一个WeakKeyDictionary,其是键的弱引用,效果和上面类似,这里就不演示了。

2.4 weakref.finalize 终结器

weakref.finalize(obj, func, *arg, **args)返回一个终结器对象,即一个回调函数,在销毁对象时会被调用。使用finalize的主要好处是它能更简便的注册回调函数,而无需保留所返回的终结器对象。

a = {1,2,3}
weakref.finalize(a, print, 'Object a is gone!')    # 将终结器注册到变量a的对象上
a = 2    # 原集合被销毁,触发终结器回调函数

在这里插入图片描述

终结器对象在调用前都被视为存活状态(可通过.alive属性查询)。你也可以主动调用终结器,调用一次后则其死亡,对象销毁时只会调用存活状态的终结器(因此主动调用过的终结器不会触发):

b = {4,5,6}
f = weakref.finalize(b, print, 'Object b is gone!')    # 注册终结器对象
f.alive    # 查询终结器存活状态
f()    # 显式调用终结器
f.alive   # 调用后状态变为死亡
b = 7     # 其注册对象销毁,但不会调用已死亡的终结器

在这里插入图片描述

三、弱引用的局限性

弱引用的应用对象存在局限性,并不是所有Python对象都可以作为弱引目标。例如列表(list),字典(dict),整型(int),元组(tuple)对象不能作为弱引用的目标。

下面对列表对象创建弱引用,显示无法创建弱引用:

list1 = [1, 2, 3]
wref = weakref.ref(list1)

在这里插入图片描述

列表和字典可以通过创建子类来绕过此限制,下面Mylist为list的子类,其实例就可以被弱引用:

class Mylist(list):pass
list1 = Mylist([1, 2, 3])
wref = weakref.ref(list1)

在这里插入图片描述

但是对于int和tuple类型,即使通过子类,也无法建立弱引用:

class Myint(int):pass
a = Myint(1)
wref = weakref.ref(a)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/290580.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在 Oracle 中使用 CREATE SEQUENCE 语句

在本文中,我们将讨论 Oracle CREATE SEQUENCE 语句,其主要目的是提供一种可靠的方法来生成唯一且连续的数值,通常用于数据库表中的主键字段。此功能对于维护数据完整性和效率、确保不同记录之间的标识符有序分配尤其重要。从本质上讲&#xf…

Linux 常用命令(1)

😇作者介绍:一个有梦想、有理想、有目标的,且渴望能够学有所成的追梦人。 🎆学习格言:不读书的人,思想就会停止。——狄德罗 ⛪️个人主页:进入博主主页 🗼专栏系列:Linux 随笔集合 …

经典永不过时 Wordpress模板主题

经得住时间考验的模板,才是经典模板,带得来客户的网站,才叫NB网站。 https://www.jianzhanpress.com/?p2484

服务器中有g++,但是查询不到,Command ‘g++‘ not found

有gcc但是查询不到g,gcc版本为9.5.0 (base) zyICML:~$ g -V Command g not found, but can be installed with: apt install g Please ask your administrator. 突然就出现这个问题,导致detectron装不上,现在有时间了专门研究下怎么解决 这…

软件测试基础理论、测试用例及设计方法、易混淆概念总结【软件测试】

一.软件测试基础理论 1.软件定义 软件是计算机系统中与硬件相互依存的一部分,包括程序、数据以及与其相关文档 的完整集合。 程序是按事先设计的功能和性能要求执行的指令序列; 数据是使程序能正常操作信息的数据结构; 文档是与程序开发、维…

【Docker】Docker安全与最佳实践:保护你的容器化应用程序

欢迎来到英杰社区: https://bbs.csdn.net/topics/617804998 欢迎来到阿Q社区: https://bbs.csdn.net/topics/617897397 📕作者简介:热爱跑步的恒川,致力于C/C、Java、Python等多编程语言,热爱跑步&#xff…

Elasticsearch 向量搜索

目标记录 ["你好,我的爱人","你好,我的爱妻","你好,我的病人","世界真美丽"] 搜索词 爱人 预期返回 ["你好,我的爱人","你好,我的爱妻"] 示例代码…

STM32之HAL开发——串口配置(源码)

串口收发原理框图(F1系列) 注意:数据寄存器有俩个一个是收一个是发,但是在标准库或者HAL库中没有特别区分开来是俩个寄存器! USART 初始化结构体详解 HAL 库函数对每个外设都建立了一个初始化结构体,比如 …

芒果YOLOv8改进145:全新风格原创YOLOv8网络结构解析图

&#x1f4a1;本篇分享一下个人绘制的原创全新风格 YOLOv8网络结构图 感觉搭配还行&#xff0c;看着比较直观。 该专栏完整目录链接&#xff1a; 芒果YOLOv8深度改进教程 订阅了专栏的读者 可以获取一份 <可以自行修改 / 编辑> 的 YOLOv8结构图修改源文件 YOLOv8结构图…

Tomcat配置https

前言&#xff1a;本文内容为实操记录&#xff0c;仅供参考&#xff01; 一、证书 CA证书申请下载不赘述了。 二、上传证书 进入tomcat根目录&#xff0c;conf同级目录下创建cert文件夹&#xff0c;并将证书两个文件上传到该文件夹&#xff1b; 三、编辑conf/server.xml文件 ① …

macOS Sonoma 14.4.1 (23E224) 正式版发布,ISO、IPSW、PKG 下载

macOS Sonoma 14.4.1 (23E224) 正式版发布&#xff0c;ISO、IPSW、PKG 下载 2024 年 3 月 26 日凌晨&#xff0c;macOS Sonoma 14.4.1 更新修复了一个可能导致连接到外部显示器的 USB 集线器无法被识别的问题。它还解决了可能导致 Java 应用程序意外退出的问题&#xff0c;并修…

FPGA高端项目:解码索尼IMX327 MIPI相机转HDMI输出,提供FPGA开发板+2套工程源码+技术支持

目录 1、前言2、相关方案推荐本博主所有FPGA工程项目-->汇总目录我这里已有的 MIPI 编解码方案 3、本 MIPI CSI-RX IP 介绍4、个人 FPGA高端图像处理开发板简介5、详细设计方案设计原理框图IMX327 及其配置MIPI CSI RX图像 ISP 处理图像缓存HDMI输出工程源码架构 6、工程源码…

第十四届蓝桥杯JavaA组省赛真题 - 特殊日期

解题思路&#xff1a; 暴力秒了 public class Main {public static void main(String[] args) {int cnt 0;for (int i 1900; i < 9999; i) {for (int j 1; j < 12; j) {for (int k 1; k < days(i, j); k) {if (sum(i) sum(j) sum(k)) cnt;}}}System.out.print…

机器学习概论—增强学习

机器学习概论—增强学习 强化学习(Reinforcement Learning, RL)或者说是增强学习,是机器学习的一个领域,旨在使智能体通过与环境的交互学习如何做出决策,它是关于在特定情况下采取适当的行动来最大化奖励。它被各种软件和机器用来寻找在特定情况下应采取的最佳行为或路径…

C++——vector类及其模拟实现

前言&#xff1a;前边我们进行的string类的方法及其模拟实现的讲解。这篇文章将继续进行C的另一个常用类——vector。 一.什么是vector vector和string一样&#xff0c;隶属于C中STL标准模板库中的一个自定义数据类型&#xff0c;实际上就是线性表。两者之间有着很多相似&…

大话设计模式之简单工厂模式

简单工厂模式&#xff08;Simple Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;属于工厂模式的一种。在简单工厂模式中&#xff0c;有一个工厂类负责根据输入参数的不同来创建不同类的实例。 简单工厂模式包含以下几个要素&#xff1a; 1. **工厂类&#xff0…

常见手撕项目C++

常见手撕项目C 设计模式单例模式饿汉模式懒汉模式 策略模式策略接口实现具体的策略&#xff08;虚函数重写&#xff09;定义上下文用户调用 设计模式 单例模式 单例模式是一种常用的软件设计模式&#xff0c;其目的是确保一个类只有一个实例&#xff0c;并提供一个全局访问点来…

OpenCV4.9关于矩阵上的掩码操作

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇:如何使用OpenCV扫描图像、查找表和时间测量 下一篇:OpenCV4.9的是如何进行图像操作 引言&#xff1a; 矩阵上的掩码操作非常简单。这个想法是&#xff0c;我们根据掩码矩阵&#xff08…

Jenkins拉取github项目相关问题

1.私有仓库问题 1.1如果你的仓库是私有的&#xff0c;21年起github就不支持账号密码的方式拉取代码了 那么就需要在github上面创建一个token (classic) 然后在Jenkins代码设置那里 然后应该就可以顺利打包了。 2.找不到pom&#xff08;多了一层文件夹&#xff09;问题 解…

【计算机组成】计算机组成与结构(四)

上一篇&#xff1a;【计算机组成】计算机组成与结构&#xff08;三&#xff09; &#xff08;7&#xff09;存储系统 计算机采用分级存储体系的主要目的是为了解决存储容量、成本和速度之间的矛盾问题。 两级存储:cache-主存、主存-辅存(虚拟存储体系) 局部性原理 ◆ 局部性…