python内存管理&垃圾回收

深入探索Python内存回收机制:原理与实践 在Python C扩展中,如果您定义了自定义的Python类型,需要正确实现它的内存管理方法。自定义类型通常会定义一个tp_dealloc成员,它是类型对象的析构函数,负责释放对象占用的所有资源。// 释放自定义类型持有的任何资源// 调用基类的析构函数(如果有的话)// ... 其他类型属性 ...// ... 其他类型方法 ... 阅读详情

1.序言

大家都知道每个语言都会有自己的垃圾回收机制,python也不例外。

Python的垃圾回收机制是以引用计数为主,标记清除和分代回收为辅加上缓存机制

市面上大部分人使用的都是CPython(以下均用Python指代),众所周知,Python是基于C语言的,所以Python的垃圾回收机制与C语言相似。

正式介绍垃圾回收机制之前,我们先了解一个重要的概念环形双向链表refchain

2.环形双向链表

在这里插入图片描述
在python程序中创建任何对象都会放在refchain链表中

而当我们创建一个对象时,程序内部还会创建一些其他数据,让我们从C源码中看看会创建哪些数据
在这里插入图片描述
大家可以看到PyObject结构体中第一行_PyObject_HEAD_EXTRA中定义了上一个对象prev和下一个对象next两个值,第二行第三行定义了引用计数器和数据类型两个值,综上,在PyObject结构体中包含了4个值

大家继续往下看PyVarObject结构体,当对象是由多个元素组成的时候,还包含一个元素个数ob_size的值

# 在C源码中如何体现每个对象中都有的相同的值:PyObject结构体(4个值)。

# 有多个元素组成的对象:PyObject结构体(4个值) + ob_size 。

# 下面给大家看一个例子就能很清楚地了解了

data = 3.14 # 创建一个浮点型数据

# 内部会创建:
#	 _ob_next = refchain中的上一个对象
#    _ob_prev = refchain中的下一个对象
#    ob_refcnt = 1
#    ob_type = float
#    ob_fval = 3.14

OK,了解了环形双象链表后,大家就能了解透彻以下Python垃圾回收机制内容了

3.引用计数

刚刚我们有学到当python程序运行时,会根据数据类型的不同找到其对应的结构体,根据结构体中的字段来进行创建相关的数据,然后将对象添加到refchain环形双向链表中

其中PyObject结构体中地ob_refcnt就是引用计数器,值默认为1,当有其他变量引用对象时,引用计数器就会发生变化

  • 引用
a = 99999 # a对应对象引用计数为1
b = a # b对应对象引用计数为1
  • 删除引用
a = 99999
b = a
del b # b变量删除;b对应对象引用计数器-1,1-1=0
del a # a变量删除;a对应对象引用计数器-1,1-1=0

# 当一个对象的引用计数器为0时,意味着没有人再使用这个对象了,这个对象就是垃圾,垃圾回收。
# 回收:1.对象从refchain链表移除;2.将对象销毁,内存归还。

大家看上面的引用计数垃圾回收是不是很方便,引用就+1,删除引用就-1

但是遇到循环引用问题,以上的解决方案就不足以处理干净系统垃圾
请添加图片描述
大家可以看到v1和v2虽然都删除引用了,但实际他们的引用计数器仍为1,仍然存在于系统中

那么怎么处理这种特殊情况呢?这就引出了下面的标记清除

4.标记清除

目的:为了解决引用计数器循环引用的不足。

实现:在python的底层再维护一个链表,链表中专门放那些可能存在循环引用的对象(list/tuple/dict/set)
在这里插入图片描述
在Python内部 某种情况下触发,回去扫描 可能存在循环应用的链表(链表2)中的每个元素,检查是否有循环引用,如果有则让双方的引用计数器 -1 ;如果是0则垃圾回收。

好了,引入了标记清除解决了循环引用的问题。但是却带来了新的问题

  • 什么时候扫描?
  • 可能存在循环引用的链表扫描代价大,每次扫描耗时久

这就引出了下面的方法分代回收

5.分代回收

在这里插入图片描述
Python将可能存在循环应用的对象维护成3个链表(链表2、3、4)

  • 0代:0代中对象个数达到700个扫描一次。
  • 1代:0代扫描10次,则1代扫描一次。
  • 2代:1代扫描10次,则2代扫描一次。

这就解决了什么时候扫描和扫描代价太大的问题,存活越久的(2代)的对象被检查得越少(大大滴良民!)

综上,这就是为什么我一开始说Python的垃圾回收机制是以引用计数为主,标记清除和分代回收为辅加上缓存机制,现在大家对这句话应该有了很深的理解

But,上述流程还能优化吗?

6.Python缓存

Python内部为了避免重复创建和销毁一些常见对象,维护了一个池

池(int)

# 启动解释器时,Python内部帮我们创建:-5、-4、..... 256
v1 = 7  # 内部不会开辟内存,直接去池中获取
v2 = 9  # 内部不会开辟内存,直接去池中获取
v3 = 9  # 内部不会开辟内存,直接去池中获取

print(id(v2),id(v3)) # 1820206787120 1820206787120

v4 = 999
v5 = 666
v6 = 666 # 超出小数据池的范围创建对象内部会开辟空间

另外我们上面说过,引用计数为0的时候,对象会被销毁,内存会被回收,理论上是不严谨的。Python对于这个步骤也做了处理

free_list(float/list/tuple/dict)

当一个对象的引用计数器为0时,按理说应该回收,内部不会直接回收,而是将对象添加到 free_list 链表中当缓存。以后再去创建对象时,不再重新开辟内存,而是直接使用free_list

v1 = 3.14  # 开辟内存,内部存储结构体中定义那几个值,并存到refchain中。

del v1     # refchain中移除,将对象添加到 free_list 中(80个),free_list满了则销毁。


v9 = 999.99 # 不会重新开辟内存,去free_list中获取对象,对象内部数据初始化,再放到refchain中。

当然free_list也是有限制的,超出限制后再删除对象也是会被直接销毁

unicode_latin1[256](str)

  v1 = "A"
  print( id(v1) ) # 输出:4517720496
  del v1
  v2 = "A"
  print( id(v1) ) # 输出:4517720496
  # 除此之外,Python内部还对字符串做了驻留机制,针对那么只含有字母、数字、下划线的字符串(见源码Objects/codeobject.c),如果内存中已存在则不会重新在创建而是使用原来的地址里(不会像free_list那样一直在内存存活,只有内存中有才能被重复利用)。
  v1 = "lucky"
  v2 = "lucky"
  print(id(v1) == id(v2)) # 输出:True
python——内存管理和垃圾回收机制 这个知识点是面试时大多都会问到的,所以在此做整理以便加强记忆。 阅读详情

相关推荐

python的垃圾回收

对于上述代码会发现,执⾏del操作之后,没有变量再会去使⽤那两个列表对象,但由于循环引⽤的问题,他们的引⽤计数器不为0,所以他们的状态:永远不会被使⽤、也不会被销毁。:对标记清除中的链表进⾏优化,将那些可能存在循引⽤的对象拆分到3个链表,链表称为:0/1/2三代,每代都可以存储对象和阈值,当达到阈值时,就会对相应的链表中的每个对象做⼀次扫描,除循环引⽤各⾃减1并且销毁引⽤计数器为0的对象。·1代,count表示0代链表扫描的次数,threshold表示0代链表扫描的次数阈值,超过则执⾏⼀次1代扫描检查。

weixin_46545179的博客 1468

python进阶(五):内存回收机制

本文详细介绍了Python的内存回收机制。Python使用引用计数和循环垃圾收集算法来自动管理内存。了解内存回收机制可以帮助你编写高效和可靠的代码,并避免内存泄漏问题。python进阶(五):内存回收机制python进阶(五):内存回收机制。

w1101662433的博客 1782

python内存管理&垃圾回收原理

“引用计数器为主,标记清除和分代回收为辅,+缓存机制。” 1.引用计数器: 1.1 环状的双向链表refchain: 在python程序中,创建的任何一个对象都会加入到这个 refchain双向链表中。 例: name = 'wuhan' new = name 操作系统会在内存中开辟一块空间存name这个对象,在内存中会为name这个对象创建一些数据 (即,一个结构体,包括上一个对象位置、下一个对象位置,本数据的数据类型,本数据的引用个数...

予非池物 1415

Python内存管理与垃圾回收深度解析

Python的内存管理和垃圾回收是一种自动的、透明的机制,但理解它的工作原理可以帮助我们写出更优化、更高效的代码。总的来说,我们应该尽量使用局部变量,使用生成器,避免循环引用,以减少内存的使用并提高程序的性能。

小小张说故事的博客 1231

海波龙(Oracle Hyperion)单点登陆问题记录

Oracle海波龙套件已经多年未更新,按Oracle官方文档实施单点登陆启用之后,SmartView工具通过专用链接方式无法登陆系统。 在抓包逆向分析之后 定位到HspSmartViewServlet类在执行以下代码时获得的ssotoken无效导致,在某大厂工作的时候曾通过在filter中截获请求的方式植入Attribute,保留账号密码并在单点程序中处理实现登陆。 但在完美世界的环境中...

cainiaoEzu的专栏 1971

STM32F103电压采集proteus仿真

基于HAL库,仿真单片机型号为stm32f103R6,代码keil5。通过单片机的ADC采集功能,测量四路电压,数据经由DMA传输,并将结果通过串口输出,结果比较确,误差在0.01V左右。目前仿真采集四路比较稳定,多了会乱码。proteus版本8.11安装包链接:https://pan.baidu.com/s/1yhNKLl1lGSU9KU0tTuAxcg?pwd=dxe8提取码:dxe8项目下载地址:.

weixin_42490599的博客 4768

Python内存管理&垃圾回收

引用计数器为主,标记清除和分代回收为辅+缓存机制 1、引用计数器 1.1 环状双向链表 refchain 在python 中创建的任何对象都会放在rechain链表中 。 内部会创建一写数据【上一个对象,下一个对象,类型,引用对象,value="王"】 name="王" ​ 在C语言源码中体现相同的值:PyObject结构体(前4个值肯定存在) 有多个元素组成的对象:PyObject结构体(前4个值肯定存在)+ob_size 。 1.2详细解析类型封装的结构体 data=3.14 内..

weixin_53042504的博客 1492

INS/伪距组合导航(1)

星间单差GNSS/INS伪距紧组合

u014430081的博客 877

python内存回收垃圾有哪些_[Python之路] 内存管理&垃圾回收

一、python源码1.准备源码解压得到文件夹:我们主要关注Include中的".h"文件以及Objects目录中的".c"文件。我们从Include和Objects中的文件类型就可以看出Python解释器是C语言编写的。2.object.h在Include文件夹中,全部都是".h"文件。这些C语言头文件中主要存放着宏、函数声明、结构体声明、全局变量等。我们在Python中所有的类都继承自Obje...

weixin_39818550的博客 87

稳定性仿真(stb闭环增益仿真)

stb仿真主要是测试电路的稳定性,例如运放在闭环电路中的增益和相位裕度的值,从而判别电路是否正常工作。 以下是stb仿真的过程: (1)调用iprobe器件 从analogLib中调iprobe器件,通过器件中的箭头标识确定接入电路的方法,箭头起点端连运放的输出端,箭头的终点端连在反馈环路的作用端。iprobe器件连入电路后相当于理想导线。(iprobe器件连接在反馈回路上) (2)analyses设置 勾选stb和frequency,此处的频率范围设置在0.1~1GHz,Probe Instance/T

qq_36686804的博客 3万+

【ENVI初学】查看影像空间分辨率及重采样

例如,如果线段长度为900米,对应的像素数量为30个,那么影像的空间分辨率为30米。通过计算长度与像素数量的比值,即可得到影像的空间分辨率。,在弹出的对话框中,输入重采样后输出文件的xy分辨率大小。在测量结果窗口中,可以看到该线段的长度以及角度。在影像上点击并拖动鼠标,绘制一条直线段。工具,选择要重采样的影像后点击ok。,避免了插值过程中光谱信息的改变。:最近邻插值法通过选择原始影像中。在ENVI中打开影像后右键选择。指示了每个像素的地理跨度(聚合为一个新像素,通常通过。方法一:查看影像的元数据。

weixin_41619112的博客 5573

python内存回收_python内存管理&垃圾回收

python内存管理&垃圾回收引用计数器环装双向列表refchain在python程序中创建的任何对象都会放在refchain连表中name = '张三'age = 18hobby = ['汽车','游艇']创建一个变量!内部会创建一些数据【上一个对象,下一个对象,类型,引用个数name = '张三'内部会创建一些数据【上一个对象,下一个对象,类型,引用计数】age = 18内部会创建一些...

weixin_39711914的博客 73

STM32实战开发(150):基于STM32的智能电力负荷控制系统开发

本文介绍了基于STM32的智能电力负荷控制系统的设计与实现,涵盖了硬件设计、软件设计、负荷预测与控制等多个方面。该系统能够实时监控电力负荷,预测未来负荷变化,并根据预测结果自动调节电力负荷,防止电网过载或浪费。未来,我们可以进一步优化该系统,加入更多的传感器数据,提升预测算法的精度,并结合大数据与云计算技术实现更为强大的远程控制与数据分析功能。

2201_76125393的博客 715

Python垃圾回收&内存管理

Python垃圾回收&内存管理 1、引用计数器 在python中创建的任何对象都会放在refchain链表中。 name = "xiaoming" age = 18 hobby = ["篮球", "美女"] 每一个对象内部都会创建一些数据[上一个对象、下一个对象、类型、引用个数](基础数据) name = "xiaoming" new = name [上一个对象、下一个对象、类型、引用个数](基础数据) + val=18(继承基础数据+不用类型的不同表现) age = 18 [上一个对象、下

weixin_41869700的博客 213

第七天 Labview进阶(7.3 Teststand简单使用)

TestStand是NI开发的自动化测试管理软件,支持多语言编程和硬件集成,广泛应用于电子产品和工业测试。安装时需注意版本选择,2022版支持离线安装。使用步骤包括:1)创建测试序列文件;2)插入测试动作并配置参数(如选择VI路径、设置变量);3)添加条件判断和延时控制;4)执行测试序列时具备流程控制功能,如失败步骤自动跳过后续测试。该软件能有效提升测试效率与准确性,通过可视化操作实现复杂测试流程管理。

weixin_38637405的博客 1733

【Python基础】FastAPI 从入门到项目实战操作详解

【Python基础】FastAPI从入门到使用实战操作详解

congge_study的博客 456

python内存清理_python内存管理&垃圾回收

python内存管理&垃圾回收引用计数器环装双向列表refchain在python程序中创建的任何对象都会放在refchain连表中name = '张三'age = 18hobby = ['汽车','游艇']创建一个变量!内部会创建一些数据【上一个对象,下一个对象,类型,引用个数name = '张三'内部会创建一些数据【上一个对象,下一个对象,类型,引用计数】age = 18内部会创建一些...

weixin_42363854的博客 668

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

复盘:Python内存管理&垃圾回收原理

1)计数器加三代回收机制 3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。

weixin_46838716的博客 319

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

python 内存管理,[Python之路] 内存管理&垃圾回收

一、python源码1.准备源码解压得到文件夹:我们主要关注Include中的".h"文件以及Objects目录中的".c"文件。我们从Include和Objects中的文件类型就可以看出Python解释器是C语言编写的。2.object.h在Include文件夹中,全部都是".h"文件。这些C语言头文件中主要存放着宏、函数声明、结构体声明、全局变量等。我们在Python中所有的类都继承自Obje...

weixin_39899776的博客 108

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

【学习笔记】Python内存管理&垃圾回收

文章目录【学习笔记】Python内存管理&垃圾回收1.引用计数器1.1 环状双向链表 refchain1.2 类型封装结构体1.3 引用计数器1.4 循环引用2.标记清除3 分代回收4 缓存机制4.1 池4.2 free_list(float/list/tuple/dict)4.3驻留机制 【学习笔记】Python内存管理&垃圾回收 1.引用计数器 1.1 环状双向链表 refchain 在python程序中创建的对象都会放在refchain链表中。 # 内部会创建【refchain中上一个

weixin_33423187的博客 293

Python内存管理&垃圾回收机制

https://www.cnblogs.com/tyyy/p/13031388.html

qq_42760539的博客 120

Python vs JavaScript 内存管理 & 垃圾回收核心区别

表格对比维度Python核心回收算法引用计数(主)+ 分代 GC(辅)标记 - 清除 + 分代复制 GC循环引用引用计数无法处理,依赖 GC 定时扫描天然支持,标记阶段自动识别对象回收时机计数归零立刻回收,实时释放统一等待 GC 批量清理,存在延迟STW 阻塞仅 GC 扫描时短暂停顿,多数操作无阻塞每次 GC 都会阻塞主线程全局常量缓存内置小整数、字符串驻留缓存无全局常驻对象缓存手动 GC 控制原生提供 gc 模块,可开关、手动触发标准语法无 API,无法强制回收。

tongbowen_123的博客 170

Python内存管理(二) —— GC垃圾回收机制(引用计数 & 隔代回收)

垃圾回收 gc机制,garbage collection(垃圾回收) 现在的高级语言如java,c#等,都采用了垃圾收集机制。而不再是c,c++里用户自己管理维护内存的方式。自己管理内存极其自由,可以任意申请内存,但如同一把双刃剑,为大量内存泄露,悬空指针等bug埋下隐患。 python里也同java一样采用了垃圾收集机制,不过不一样的是python采用的是引用计...

hxxjxw的博客 2278

如何在Python中显式释放内存?

根据Python官方文档,您可以强制垃圾收集器释放未引用的内存gc.collect()。例: import gc gc.collect() 所属网站分类: python高级 >综合&其它 作者:lg 链接:http://www.pythonheidong.com/blog/article/455/ 来源:python黑洞网 ...

weixin_39363245的博客 2564

Python中的内存管理:垃圾回收机制是如何工作的?

本文摘要:Python通过自动内存管理机制简化了开发者的工作,其核心是垃圾回收机制。文章首先对比了C语言(需手动管理内存)和Python(自动内存管理)的差异,强调理解Python内存管理的重要性。接着分析了Python内存管理的4层架构:应用层、解释器层、内存分配层和系统层,并展示了如何检测内存使用情况。最后,探讨了Python对象在内存中的表示方式,包括引用计数等机制。理解这些机制有助于编写高效Python程序,避免内存泄漏等问题的发生。

闲人编程的博客 1175

Python 垃圾回收机制深度解析

fill:#333;color:#333;color:#333;fill:none;存活超过阈值存活超过阈值程序结束回收失败回收失败回收失败新对象创建第0代对象第1代对象第2代对象内存释放立即回收。

YAnt的博客 1354
上一篇: python元类
下一篇: Linux根目录下文件的含义(FHS标准)
爱学习的六金同学
博客等级 码龄7年 4粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值