Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >python 的内存管理与垃圾收集

python 的内存管理与垃圾收集

作者头像
用户3147702
发布于 2022-06-27 04:56:38
发布于 2022-06-27 04:56:38
37500
代码可运行
举报
运行总次数:0
代码可运行

1. 概述

我们知道,Python 不需要提前声明变量,也无需指定其类型,变量的类型和内存占用都是运行时决定的。 赋值时,解释器会根据语法和右侧的操作数来决定新对象的类型。 在对象创建后,一个该对象的应用会被赋值给左侧的变量。 Python 程序的内存分配和释放都是解释器进行操作的,不需要程序员手动处理。

2. 引用计数

Python 使用了引用计数这一简单技术。也就是说 Python 内部记录着所有使用中的对象各有多少引用。 当一个对象的引用计数变为 0 时, 它被垃圾回收。 当对象被创建并(将其引用)赋值给变量时,该对象的引用计数就被设置为 1。

2.1. 引用计数的增加

在以下情况中,引用计数会增加: 1. 对象被创建 — x = 123 2. 另外的别名被创建 — y = x 3. 作为参数被传递给函数 — foobar(x) 4. 成为容器对象的元素 — myList = [1, x, 5]

2.2. 引用计数的减少

以下情况引用计数会减少: 1. 本地引用离开其作用范围 — 如函数调用结束 2. 对象别名显式销毁 — del y 3. 对象的一个别名被赋值为其他对象 — y = ’abc’ 4. 对象被从容器中移除 — myList.remove(x) 5. 容器本身销毁 — del myList

3. 垃圾收集

不再被使用的内存会被垃圾收集机制释放,而垃圾收集器就负责释放内存。 当对象引用计数为 0 就会立即出发内存回收动作。 我们都知道,java 是通过可达性判断对象是否需要回收的,他之所以不通过引用计数算法,是因为可能会有循环引用的存在。

下图展示了什么是循环引用:

这两个列表的引用计数永远不可能到0,如果仅仅依赖引用计数,那么他们将永远无法被收集。

在 python 中,list,set,dict,class,instance 等类型的对象可以持有其他对象的引用,他们被称为 container 对象,因此循环引用发生在 container 对象之间。 python 维护了三个可收集对象链表,用来收集和跟踪所有的 container 对象。 所有的 python 对象都由两个部分构成:PyObject_HEAD + 对象本身数据,而 container 对象则在其 PyObject_HEAD 前有一个 pyGC_Head,这个结构就是可收集对象链表节点结构。 在创建 container 对象时,解释器会调用 _PyObject_GC_TRACK 方法将对象加入到可收集对象链表中。 当对象销毁时,解释器会调用 _PyObject_GC_UNTRACK 方法将该 container 对象从可收集对象链表中移除。

4. 分代收集

分代收集是典型的为了提高垃圾收集的效率,所采用的“空间换时间的策略”。 python 也同样引入了分代收集的思想,所以前面提到 python 维护了三个可收集对象链表,所有属于同一”代”的内存块都链接在同一个链表中。 垃圾收集的频率随着“代”的存活时间的增大而减小,这是因为活得越长的对象,就越不可能是垃圾,就应该减少去收集的频率。 当一次垃圾收集过程中没有被回收的对象就会从当前的代自动移入到下一个代中。 每个代都有自己的容量阈值,当分代中的 container 对象超过了阈值时会触发垃圾回收。

5. 垃圾回收过程

python 采用标记-清除的方式来回收 container。 主要分以下六步: 1. 将所有比当前代年轻的分代中的对象都放到当前代链表中 2. 遍历对象链表,拷贝每个对象的引用计数到 PyGC_Head 中的 gc.gc_ref 作为引用计数副本 3. 判断对象是否符合循环引用,将循环引用的对象的 gc.gc_ref -1,从而获取有效引用计数 4. 将链表中引用计数为 0 与引用计数大于 0 的对象拆分成 reachable 和 unreachable 两个链表 5. reachable 中所有存活对象放入下一分代 6. 回收 unreachable 链表中的所有对象

6. python 中的 gc 模块

python 提供了 gc 模块,用来提供观察和手动使用gc的接口。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import gc

gc.set_debug(gc.DEBUG_STATS | gc.DEBUG_LEAK)
gc.collect()

7. 参考资料

http://python.jobbole.com/83548/?utm_source=blog.jobbole.com&utm_medium=relatedPosts。 http://python.jobbole.com/87843/ https://www.cnblogs.com/pinganzi/p/6646742.html#_label8。 https://www.jianshu.com/p/1e375fb40506。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-09-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小脑斧科技博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Python垃圾回收机制详解「建议收藏」
  平时在写代码的时候,关注的是写出能实现业务逻辑的代码,因为现在计算机的内存也比较宽裕,所以写程序的时候也就没怎么考虑垃圾回收这一方面的知识。俗话说,出来混总是要还的,所以既然每次都伸手向内存索取它的资源,那么还是需要知道什么时候以及如何把它还回去比较好。嘻嘻。
全栈程序员站长
2022/11/19
2K0
Python垃圾回收机制详解「建议收藏」
Python 的垃圾回收机制
如果减引用之后计数器不为0就会通过 _Py_CHECK_REFCNT检查引用计数器是否为负。
CS实验室
2021/03/22
7430
Python 的垃圾回收机制
python源码阅读笔记之GC
引用计数法 增量: 各个对象的内部都有计数器。如果对象的引用数量增加,就在计数器上加1,否则减1 #define Py_INCREF(op) ( \ _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \ ((PyObject*)(op))->ob_refcnt++) 下面的是含有NULL检查的宏 #define Py_XINCREF(op) do { if ((op) == NULL) ; else
哒呵呵
2018/08/06
8680
Python 垃圾回收机制与原理解析
Python 作为一门解释型语言,以代码简洁易懂著称,我们可以直接对名称赋值,而不必声明类型,名称类型的确定、内存空间的分配与释放都是由 Python 解释器在运行时进行的
公众号机器学习与AI生成创作
2021/10/20
1.1K0
Python 垃圾回收机制与原理解析
《Python 源码剖析》一些理解以及勘误笔记(3)
以下是本人阅读此书时理解的一些笔记,包含一些影响文义的笔误修正,当然不一定正确,贴出来一起讨论。 注:此书剖析的源码是2.5版本,在python.org 可以找到源码。纸质书阅读,pdf 贴图。
s1mba
2017/12/28
1.2K0
《Python 源码剖析》一些理解以及勘误笔记(3)
Python垃圾回收机制
如果将应用程序比作人的身体:所有你所写的那些优雅的代码,业务逻辑,算法,应该就是大脑。垃圾 回收就是应用程序就是相当于人体的腰子,过滤血液中的杂质垃圾,没有腰子,人就会得尿毒症,垃圾 回收器为你的应该程序提供内存和对象。如果垃圾回收器停止工作或运行迟缓,像尿毒症,你的应用程序效 率也会下降,直至最终崩溃坏死。
星陨1357
2023/03/14
6700
Python垃圾回收机制
剖析 Python 面试知识点(二)- 内存管理和垃圾回收机制
Python 中一切皆对象,对象又可以分为可变对象和不可变对象。二者可以通过原地修改,如果修改后地址不变,则是可变对象,否则为不可变对象,地址信息可以通过id()进行查看。
天澄技术杂谈
2019/04/05
1.1K0
Python 是如何管理内存的?
在 GitHub 看到一篇很不错的学习资料,其中提到 Python 是如何管理内存的,我看完后很有收获,如下:
somenzz
2021/08/19
1K0
Python的垃圾回收机制(引用计数+标
我们都知道Python一种面向对象的脚本语言,对象是Python中非常重要的一个概念。在Python中数字是对象,字符串是对象,任何事物都是对象,而它们的核心就是一个结构体--PyObject。
py3study
2020/01/17
1.2K0
python内存管理与垃圾回收
陷阱:需要注意,因为给getrefcount传递了参数a,因此也导致了引用计数+1,所以打印的结果是2,但是实际引用计数是1,故:引用计数=sys.getrefcount(xxx) - 1
zy010101
2022/05/05
5100
python进阶(7)垃圾回收机制
现在的高级语言如java,c#等,都采用了垃圾回收机制,而不再像c,c++里,需要用户自己管理内存。自己管理内存及其自由,可以任意申请内存,但这如同一把双刃剑,可能会造成内存泄漏,空指针等bug。 python中也同java一样采用了垃圾回收机制,不过不一样的是:python采用的是引用计数机制为主,标记清除和分代回收两种机制为辅的策略
全栈程序员站长
2022/09/19
7370
深入理解Python内存管理与垃圾回收,再也不怕问了(二)
如果一个对象的引用计数为0,Python解释器就会回收这个对象的内存,但引用计数的缺点是不能解决循环引用的问题,所以我们需要标记清除和分代回收。
宇宙之一粟
2020/10/26
6380
深入理解Python内存管理与垃圾回收,再也不怕问了(二)
python垃圾回收机制(引用计数)
垃圾回收(Garbage Collection)大家应该多多少少都听过,但是什么是垃圾回收呢?我们这里说的垃圾回收肯定不是把垃圾丢进垃圾桶。现在的高级语言Java,C#等,都采用了垃圾回收机制,而不再是C,C++里用户自己管理维护内存的方式,自己管理内存是很自由,但是可能出现内存泄漏,悬空指针等问题。而垃圾回收机制作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来给其他对象使用。
全栈程序员站长
2022/09/09
7190
python垃圾回收机制(引用计数)
玩懂Python垃圾回收机制,又有时间可以摸鱼了
我们写过C语言、C++的朋友们都知道,C语言是没有垃圾回收这种说法的。手动分配以及释放内存都是需要我们的程序员自己动手完成。不管是“内存泄漏” 还是野指针都是让开发者非常头疼的问题。所以C语言开发提及讨论最多的话题就是内存管理了。but对于其他高级语言来说,例如Java、C#、Python等高级语言,已经具备了垃圾回收机制。这样可以屏蔽内存管理的复杂性,使开发者可以更好的关注核心的业务逻辑。
查理不是猹
2021/12/12
8920
垃圾收集策略与算法
程序计数器、虚拟机栈、本地方法栈随线程而生,也随线程而灭;栈帧随着方法的开始而入栈,随着方法的结束而出栈。这几个区域的内存分配和回收都具有确定性,在这几个区域内不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟随着回收了。
黑洞代码
2021/04/23
3560
Python 进阶:浅析「垃圾回收机制」
花下猫语:近半个月里,我连续写了两篇关于 Python 中内存的话题,所关注的点都比较微小,猎奇性质比实用性质大。作为对照,今天要分享一篇长文,是跟内存相关的垃圾回收话题,一起学习进步吧! 作者:二两
Python猫
2019/09/19
2.2K0
Python 进阶:浅析「垃圾回收机制」
Java 垃圾收集器的垃圾收集算法
在 Java 中,垃圾回收是个基础而有趣的话题,本文主要讲解 Java 垃圾收集器的垃圾收集算法,首先,需要理解几个概念:
CS实验室
2021/03/22
5230
Java 垃圾收集器的垃圾收集算法
垃圾收集算法 Krains 2020-08-06
每个对象保存一个整型的引用计数器,假设有一个对象A,如果别的对象引用了A,就让A对象的引用计数器加1,如果引用失效了,计数器减1,当计数器为0的时候,该对象就是垃圾。
Krains
2020/08/10
3000
垃圾收集算法  Krains 2020-08-06
JVM垃圾收集详解
为每个对象标记一个引用数量,当这个对象被另外一个对象引用时它的引用数据就加一,当另外一个对象释放了对它的引用它的引用数量就减一。当它的引用变为0时意味着没有对象引用,就可以回收了
Java学习录
2019/05/15
4220
垃圾收集机制与内存分配策略
Java 语言与其他编程语言有一个非常突出的特点,自动化内存管理机制。而这种机制离不开高效率的垃圾收集器(Garbage Collection)与合理的内存分配策略,这也是本篇文章将要描述的两个核心点。
Single
2018/04/04
1.1K2
垃圾收集机制与内存分配策略
相关推荐
Python垃圾回收机制详解「建议收藏」
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验