python垃圾回收机制(GC)相关问题
在使用python中很少遇到内存溢出的问题,也不关心内存的管理问题,这是高级语言自带的处理机制,将内部的垃圾空间清除。
要清楚是怎么回收垃圾的,那我们应该先明白什么情况下产生垃圾,就涉及到python内部的对象管理方法。
对于int类型的变量在[5, 257)范围内是共用对象常驻内存,不在此范围内的话一个变量建立一个对象。
单个字符是常驻内存共用对象,字符串是引用计数机制(相同的值指向同一个对象)
a = 256
a1 = 256
b = 257
b1 = 257
id(a) == id(a1)
Out[6]: True
id(b) == id(b1)
Out[7]: False
c1 = 'a'
c = 'a'
d = 'sdsds4'
d1 = 'sdsds4'
id(c) == id(c1)
Out[12]: True
id(d) == id(d1)
Out[13]: True
首先在对象管理上已经做到了最小化的内存开销,并不是一个变量一个对象,而是多种方案结合。
那再看垃圾回收的机制,与C/C++有别的是python内部实现了自动的垃圾回收,而无需用户考虑什么时候销毁一个对象或变量。python的垃圾回收机制是以引用计数机制为主,标记-清除和分代收集两种机制为辅的综合方案。
引用计数机制
上面说的字符串内存管理就是引用计数,当创建一个字符串a='test',之后再创建一个b = 'test‘,其实变量a/b指向的是一个对象’test',这个对象被引用的次数是2,但是当我们改变b='test1‘,这个时候b新建了一个对象'test1'并且引用计数为1,相应的a引用计数也变为了1,这就是引用计数。
那么怎么通过引用计数回收垃圾对象呢?还是上面那个案例,此时再把变量a赋值a='test2',那么又新建了一个对象'test2'并且引用计数为1,此时之前的'test'引用计数变为0,就意味没有任何变量使用了该对象,那这个对象就是垃圾对象被销毁。
引用计数简单方便但是也有弊端:计数占用内存、在相互引用的对象中计数永远不会变为0,所以还引入了标记-清除和分代收集。
标记-清除
标记清除的概念类似于引用计数,只是不同的是当引用计数为0的时候就给这个对象打上一个标签”可清除“,但是不会立马清除,而是会等到系统给程序分配的内存要用完之时,停下来将可清除标签的对象销毁然后继续。
分代回收
首先看上面说的引用计数的弊端在两个变量循环引用中,计数永远不可能是0.
b = [3,4]
a = [1,2]
a.append(b)
b.append(a)
a
Out[25]: [1, 2, [3, 4, [...]]]
b
Out[26]: [3, 4, [1, 2, [...]]]
del a
b
Out[29]: [3, 4, [1, 2, [...]]]
当删除a/b变量时对应的内存对象应用计数还是1是无法删除的,此时分代回收就发挥了他的作用,当创建一个对象是将它向上面对象一个放在一个抽象的链条上,这条链条就是零代链条。
然后当零代链条上对象数达到阀值就对上面相互引用的对象进行检测,将相互引用的对象的计数减1,再标记清除垃圾,此时剩下的对象移到一代链条,当一代链条到达阀值就重复零代的检测方式,将剩下对象移到二代,就以此类推进行下去。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
python常用内建属性大全
在python中创建一个类,它不仅有我们自定义的属性和方法,还有与生俱来的一些属性和方法,我们叫它内建属性。 下面是类常用内建属性列表。 常用专有属性 说明 触发方式 __init__ 构造初始化函数 创建实例后,赋值时使用,在__new__后 __new__ 生成实例所需属性 创建实例时 __class__ 实例所在的类 实例.__class__ __str__ 实例字符串表示,可读性 print(类实例),如没实现,使用repr结果 __repr__ 实例字符串表示,准确性 类实例 回车 或者 print(repr(类实例)) __del__ 析构 del删除实例 __dict__ 实例自定义属性 vars(实例.__dict__) __doc__ 类文档,子类不继承 help(类或实例) __getattribute__ 属性访问拦截器 访问实例属性时 __bases__ 类的所有父类构成元素 类名.__bases__ __init__ 负责一个类实例化中的初始化操作 __new__ 在创建实例化时发生作用,在__init__之前执行,主要作用是创建实例对象,典型的应用是在单利模...
- 下一篇
python另类处理Google和12306的图形验证
随着反爬虫的深入,后来不仅有滑块验证,还出现了点选验证、图形验证、汉字图形验证、其中较为知名的是Google的图形验证和12306的图形验证,以及知乎出现的倒立汉字验证。 应对图形验证的方式除了对接专业的验证平台以外,我们还可以通过处Email、微信将图片发给自己来选择点击位置,今天就分享如何方便自己点击选择。 下面是一张12306图形验证码 遇到这种情况,在大型项目中一般直接对接专业处理平台,在小项目中就自己点选了,但是无界面模式下又怎么选择?那当然是通过邮件或者微信发送到手机,即使受到了验证码也很难做出处理。 但是将上面的图片处理一下做成下面的样子: 直接在微信回复图片中的编码,每个编号中间的十字光标就是选择该编号后会点击的坐标。同时可以定义图片分割的大小,可以分割得更加密集或者更加稀疏。 每个单元格就像一个像素位置,只是不同的是我们只需要说出编号,让程序自动找到坐标来点击。 代码如下: fromPILimportImage fromPILimportImageDraw,ImageFont defimages(file,n,m): """:paramfile:图片路径:paramn...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- 2048小游戏-低调大师作品
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Mario游戏-低调大师作品
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker使用Oracle官方镜像安装(12C,18C,19C)