Python 内存管理概述Python 内存管理概述

学过 C++ 的朋友都知道,C++ 需要手动释放申请的内存空间,对于程序员来说是相对麻烦的,那么一向以简单著称的 Python 是怎么管理程序中对象占用的内存空间的呢?本文就介绍一下 Python 的内存管理机制:

在讨论 Python 的内存管理之前,我们需要了解两个概念,栈内存和堆内存;栈内存,是操作系统内存中开辟的一块以先进后出或后进先出原理存储对象逻辑内容的内存区域,栈内存通常来说比较小;堆内存,是操作系统在内存中开辟的一块以大顶堆或小顶堆原理存储对象实际内容的内存区域,堆内存通常来说比较大;二者除了在存储原理、占用空间大小上有区别之外,实际上二者对于各自内存空间的管理方式也是不同的;

举个例子,比如 Python 中某个函数内部定义 了 stack = 100,那么当该函数运行之后,操作系统就会在堆内存中开辟一块区域用于存储 100 这个整数值;另外会将 stack 对象的逻辑内容自动放入栈内存中,这里的逻辑内容是什么意思呢?如下图所示,其实就是栈中保存了 stack 变量名&xxx(指向 100 占用的内存空间的物理地址)当函数运行结束后,栈内存中的内容会被操作系统自动回收,而堆内存中的内容操作系统不会自动回收;随着主机程序执行越来越多,那么堆内存空间迟早有一刻会被消耗完,从而产生内存溢出(内存剩余空间无法满足程序需要的内存空间)现象,而且如果不能合理的管理内存,还会造成内存泄漏(已申请的内存无法及时释放)的问题;这显然都是不能接受的,所以针对这两个问题, Python 创建了自身独特的内存管理机制及时回收堆内存不再使用的那部分内存空间!

因此 Python 的内存管理,针对的是堆内存!有了基本的认识,我们接下来就从三个角度解释一下 Python 是如何进行堆内存管理的:

引用计数

还是上面的例子,当程序运行到 stack = 100 这条语句时,引用计数的思想很简单,就是栈内存中的对象引用堆内存中的 100 时,每引用一次就为 100 这个整数值的标记(引用计数器) +1,当清除对象比如 del stack 后就代表这个对象已经不存在了,所以指向 100 的引用自然也不存在,那么就为 100 这个整数值标记 -1,一旦堆内存中某个内存区域的标记为 0 时,内存管理机制就会将其回收;

什么情况下引用计数器 +1

  • **初始化变量:**stack = 100
  • **间接引用:**stack1 = stack

什么情况下引用计数器 -1

  • **对象名被显式销毁:**del stack
  • **对象名与原空间解除绑定:**stack = 50

标记清除

引用计数看上去是一种完美的解决方案,但实际上它存在一些潜在的问题,如下所示:

list1 = [1, 2, 3] # list1 的标记 +1
list2 = [4, 5, 6] # list2 的标记 +1
list1.append(list2) # list2 的标记 +1
list2.append(list1) # list1 的标记 +1

上述代码执行完之后,list1 和 list2 的引用计数标记都变成 2,如下图所示:此时如果程序员觉得 list1 和 list2 都无需再继续使用,便执行 del list1 和 del list2,随后 list1 和 list2 的引用计数标记变成 1 不等于 0,但实际上 list1 和 list2 的生命周期已经结束,由于引用计数机制在循环引用情形下的缺陷,list1 和 list2 占用的堆内存并不会被释放;这种现象对于所有可变对象都会发生,就是前文所说的内存泄漏!除了内存泄漏,引用计数还存在浪费额外资源存储引用计数器二次释放(如何解决二次释放参考**这篇文章**)等问题!

循环引用

如何解决内存泄漏

Python 是这样规定的,针对上例中的列表互相引用,程序结束时栈内存中的 list1 和 list2 都指向了堆内存中的 [4, 5, 6],此时执行 del list1 和 del list2 意味着 list1 和 list2 占用的堆内存实际上没有任何栈内存对象指向它,只剩下二者之间的循环引用!放任这种现象不管,久而久之堆内存肯定会被占满,当堆内存空间占满时,Python 就会采取垃圾回收算法(GC)通过标记清除的方法回收掉 list1 和 list2 这一类的堆内存(即使其引用计数标记为 1)具体做法是,从 list1 的栈内存出发与堆内存进行连线(实际上就是将每个栈内存和堆内存的空间看作节点,之间的连线看作边,构成有向图)连线上包含的堆内存空间都会标记(有标记的就是存活对象,不被清除,因为既然堆内存能与栈内存连接,反过来就证明栈内存中有指向堆内存的指针)没有标记的堆内存则会被回收;所以针对上图的现象,从 list1 和 list2 出发都无法连接到堆内存中的两个内存区域 [1, 2, 3] 和 [4, 5, 6],就会被清除!

分代回收

每次进行垃圾回收都扫描一遍堆内存实际上很耗时,Python 在此基础上提出了分代回收机制,就是为所有堆内存的对象设置优先级,每隔一定时间扫描堆内存,为所有标记过的存活对象的阈值 +1,阈值增加到一定数量就会上升一个优先级(代表该堆内存可能接下来还会用到,因此下一轮扫描就不会扫描这些高优先级的内存空间,从而节省时间)

以上就是“Python 内存管理概述”的全部内容,希望对你有所帮助。

关于Python技术储备

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

在这里插入图片描述

二、Python必备开发工具

img

三、Python视频合集

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

img

四、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

img

五、Python练习题

检查学习结果。

img

六、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

img

最后祝大家天天进步!!

上面这份完整版的Python全套学习资料已经上传至CSDN官方,朋友如果需要可以直接微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】。

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值