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

news2024/11/14 21:22:52

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 = name
        self.salary = salary
    def __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.coloradmin.cn/o/1551910.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

精灵传信系统 匿名性系统 支持网站+小程序双端源码

精灵传信支持在线提交发送短信,查看回复短信,在线购买额度,自定义对接易支付,设置违禁词,支持网站小程序双端。 项目 地 址 : runruncode.com/php/19720.html 环境要求: PHP > 73 MySQL>5.6 Ngi…

网上兼职赚钱攻略:六种方式让你轻松上手

在互联网时代,网上兼职已经成为一种非常流行的赚钱方式。对于许多想要在家里挣钱的人来说,网上兼职不仅可以提供灵活的工作时间,还可以让他们在自己的兴趣领域中寻求机会,实现自己的财务自由。 在这里,我将为您介绍六…

基于Java仓库管理系统设计与实现(源码+部署文档+论文)

博主介绍: ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精彩专栏 推荐订阅 👇🏻 不然下次找不到 Java项目精品实…

【每日跟读】常用英语500句(200~300)

【每日跟读】常用英语500句 Home sweet home. 到家了 show it to me. 给我看看 Come on sit. 过来坐 That should do nicely. 这样就很好了 Get dressed now. 现在就穿衣服 If I were you. 我要是你 Close your eyes. 闭上眼睛 I don’t remember. 我忘了 I’m not su…

排序C++

题目 法1 sort升序排序&#xff0c;再逆序输出 #include<iostream> #include<algorithm> using namespace std;const int N 5e53;//注意const&#xff0c;全局 int a[N]; int main() {//错误int N5e53;//错误const int a[N];int n;cin >> n;for (int i 1;…

用Python机器学习模型预测世界杯结果靠谱吗?

看到kaggle、medium上有不少人用球队的历史数据来进行建模预测&#xff0c;比如用到泊松分布、决策树、逻辑回归等算法&#xff0c;很大程度上能反映强者恒强的现象&#xff0c;比如巴西、英格兰等大概率能进8强&#xff0c;就像高考模拟考试成绩越好&#xff0c;大概率高考也会…

内网穿透_ICMP_icmpsh

目录 一、ICMP协议详解 二、ICMP隧道 (一) 为什么会使用ICMP (二) 实验环境 (三) 操作流程 1. 下载icmpsh 2. 下载并安装依赖 3. 关闭本地icmp响应 4. 攻击机启动服务端开始监听 5. 靶机启动工具客户端 6. 攻击机接受到靶机传来的数据 三、郑重声明 一、ICMP协议详…

论文《Exploring to Prompt for Vision-Language Models》阅读

论文《Exploring to Prompt for Vision-Language Models》阅读 论文概况论文动机&#xff08;Intro&#xff09;MethodologyPreliminaryCoOp[CLASS]位置Context 是否跨 class 共享表示和训练 ExperimentsOverall ComparisonDomain GeneralizationContext Length (M) 和 backbon…

RAFT:让大型语言模型更擅长特定领域的 RAG 任务

RAFT&#xff08;检索增强的微调&#xff09;代表了一种全新的训练大语言模型&#xff08;LLMs&#xff09;以提升其在检索增强生成&#xff08;RAG&#xff09;任务上表现的方法。“检索增强的微调”技术融合了检索增强生成和微调的优点&#xff0c;目标是更好地适应各个特定领…

解决 vue activited 无效问题

当对页面APP.vue组件router-view标签使用了keep-alive之后在组件activated状态时不会发送请求&#xff0c;这时需要使用 keep-alive标签的 exclude属性排除需要重新发送请求的组件。需要注意exclude的值要和组件本身的name值要一致&#xff0c;如果不一致就会不生效。目前我出现…

MySQL 日志:undo log、redo log、binlog 有什么用?

资料来源 : 小林coding 小林官方网站 : 小林coding (xiaolincoding.com) 从这篇「执行一条 SQL 查询语句&#xff0c;期间发生了什么&#xff1f; (opens new window)」中&#xff0c;我们知道了一条查询语句经历的过程&#xff0c;这属于「读」一条记录的过程&#xff0c;如下…

分布式处理

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;这是我作为学习笔记原理篇的最后一章&#xff0c;一台计算机在数据中心里是不够的。因为如果只有一台计算机&#xff0c;我们会遇到三个核心问题。第一个核心问题&#xff0c;叫作垂直扩展和水平扩展的选择问题&#xff0c;…

ThreadPool-线程池使用及原理

1. 线程池使用方式 示例代码&#xff1a; // 一池N线程 Executors.newFixedThreadPool(int) // 一个任务一个任务执行&#xff0c;一池一线程 Executors.newSingleThreadExecutorO // 线程池根据需求创建线程&#xff0c;可扩容&#xff0c;遇强则强 Executors.newCachedThre…

MrDoc寻思文档 个人wiki搭建

通过Docker快速搭建个人wiki&#xff0c;开源wiki系统用于知识沉淀&#xff0c;教学管理&#xff0c;技术学习 部署步骤 ## 拉取 MrDoc 代码 ### 开源版&#xff1a; git clone https://gitee.com/zmister/MrDoc.git### 专业版&#xff1a; git clone https://{用户名}:{密码…

CXL技术市场概览

在2019年&#xff0c;Intel主导联合多家阿里巴巴、Facebook(也就是改名后Meta)、谷歌、Dell、华为、思科、微软、HPE最初的八巨头&#xff0c;发布了新的互联协议CXL&#xff0c;全称Comupte Express Link。由于在服务器领域享有绝对领导地位&#xff0c;Intel一经号令&#xf…

【Linux】 centos7安装卸载SQL server(2017、2019)

一、安装配置 准备一个基础Linux配置&#xff1a; 内存为20GB 运行内存为2GB的系统&#xff08;数据库小于2GB安装不了&#xff09; 1、网络配置 我们需要进行网络的连接 进入 cd /ect/sysconfig/network-script/ 编辑文件ifcfg-ens33 vi ifcfg-ens33 Insert键进行编辑 把ONBOO…

软件设计师24--概念设计阶段

软件设计师24--概念设计阶段 考点1&#xff1a;概念设计过程考点2&#xff1a;E-R图属性E-R模型-联系类型判断例题&#xff1a;E-R模型-联系类型判断扩充的E-R模型 考点1&#xff1a;概念设计过程 需求分析 --> 抽象数据 --> 设计局部ER模型 --> 合并局部模型消除冲突…

为什么Python不适合写游戏?

知乎上有热门个问题&#xff1a;Python 能写游戏吗&#xff1f;有没有什么开源项目&#xff1f; Python可以开发游戏&#xff0c;但不是好的选择 Python作为脚本语言&#xff0c;一般很少用来开发游戏&#xff0c;但也有不少大型游戏有Python的身影&#xff0c;比如&#xff1…

域环境共享文件夹,容量配额管理

首先&#xff0c;我们先创建一个新的磁盘&#xff0c;必须在服务器关机的状态下创建&#xff0c;只有在关机状态下才能创建NVMe类型的磁盘。 打开此电脑&#xff0c;右击创建的磁盘&#xff0c;点击属性。 点击共享&#xff0c;点击高级共享。 将共享此文件夹勾选上&#xff0c…

腾讯云服务器新购、续费、升级如何领取优惠券?

腾讯云作为国内领先的云计算服务提供商&#xff0c;一直致力于为用户提供高效、稳定、安全的云服务。为了吸引广大用户上云&#xff0c;腾讯云经常推出各种优惠活动&#xff0c;其中就包括服务器新购、续费、升级的优惠券。本文将为大家详细介绍如何领取腾讯云服务器优惠券&…