Python小白垃圾回收机制入门


Posted in Python onJune 09, 2020

引用计数

Python默认的垃圾收集机制是“引用计数”,每个对象维护了一个ob_ref字段。它的优点是机制简单,当新的引用指向该对象时,引用计数加1,当一个对象的引用被销毁时减1,一旦对象的引用计数为0,该对象立即被回收,所占用的内存将被释放。它的缺点是需要额外的空间维护引用计数,不过最主要的问题是它不能解决“循环引用”。

什么是循环引用?A和B相互引用而再没有外部引用A与B中的任何一个,它们的引用计数虽然都为1,但显然应该被回收,例子:

a = { } # a 的引用为 1
b = { } # b 的引用为 1
a['b'] = b # b 的引用增 1,b的引用为2
b['a'] = a # a 的引用增 1,a的引用为 2
del a # a 的引用减 1,a的引用为 1
del b # b 的引用减 1, b的引用为 1

在这个例子中,del语句减少了 a 和 b 的引用计数并删除了用于引用的变量名,可是由于两个对象各包含一个对方对象的引用,虽然最后两个对象都无法通过名字访问了,但引用计数并没有减少到零。因此这个对象不会被销毁,它会一直驻留在内存中,这就造成了内存泄漏。为了解决循环引用问题,Python引入了标记-清除和分代回收两种GC机制。

标记清除

标记——清除(Mark——Sweep)是一种基于追踪(Tracing)回收技术实现的垃圾回收算法,对象之间通过引用(指针)连在一起,构成一个有向图,对象构成这个有向图的节点,而引用关系构成这个有向图的边。从根对象(root object)出发,沿着有向边遍历对象,可达的对象标记为有用的对象,不可达的对象就是要被清除的对象。所谓根对象就是一些全局引用对象和函数栈中的引用,这些引用所引用的对象是不可被删除的。

标记清除算法作为Python的辅助垃圾收集技术主要处理的是一些容器对象,比如list、dict、tuple,instance等,因为对于字符串、数值对象是不可能造成循环引用问题。Python使用一个双向链表将这些容器对象组织起来。

分代回收

分代回收是一种以空间换时间的操作方式,Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,Python将内存分为了3“代”,分别为年轻代(第0代)、中年代(第1代)、老年代(第2代),他们对应的是3个链表,它们的垃圾收集频率与对象的存活时间的增大而减小。新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。同时,分代回收是建立在标记清除技术基础之上。

分代回收同样作为Python的辅助垃圾收集技术处理那些容器对象。

实例扩展:

引用计数实例

import sys
class A():
 def __init__(self):
  '''初始化对象'''
  print('object born id:%s' %str(hex(id(self))))
 def f1():
 '''循环引用'''
 while True:
  c1=A()
  c2=A()
  c1.t=c2
  c2.t=c1
  del c1
  del c2

到此这篇关于Python小白垃圾回收机制入门的文章就介绍到这了,更多相关Python垃圾回收机制详解内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python 多进程通信模块的简单实现
Feb 20 Python
Python按行读取文件的简单实现方法
Jun 22 Python
分享一下如何编写高效且优雅的 Python 代码
Sep 07 Python
python web.py开发httpserver解决跨域问题实例解析
Feb 12 Python
python爬虫_实现校园网自动重连脚本的教程
Apr 22 Python
python批量创建指定名称的文件夹
Mar 21 Python
Python中新式类与经典类的区别详析
Jul 10 Python
Python简易计算器制作方法代码详解
Oct 31 Python
pytorch逐元素比较tensor大小实例
Jan 03 Python
Django def clean()函数对表单中的数据进行验证操作
Jul 09 Python
详解pytorch tensor和ndarray转换相关总结
Sep 03 Python
OpenCV3.3+Python3.6实现图片高斯模糊
May 18 Python
Python中如何添加自定义模块
Jun 09 #Python
sklearn线性逻辑回归和非线性逻辑回归的实现
Jun 09 #Python
Python如何避免文件同名产生覆盖
Jun 09 #Python
对Keras中predict()方法和predict_classes()方法的区别说明
Jun 09 #Python
Python嵌入C/C++进行开发详解
Jun 09 #Python
Keras load_model 导入错误的解决方式
Jun 09 #Python
如何用python处理excel表格
Jun 09 #Python
You might like
关于zend studio 出现乱码问题的总结
2013/06/23 PHP
深入解析fsockopen与pfsockopen的区别
2013/07/05 PHP
JavaScript实现滚动栏效果的方法
2015/04/27 PHP
php利用smtp类实现电子邮件发送
2015/10/30 PHP
laravel5 Eloquent 实现事务方式
2019/10/21 PHP
详解PHP中curl_multi并发的实现
2020/06/08 PHP
Nigma vs Alliance BO5 第三场2.14
2021/03/10 DOTA
不错的asp中显示新闻的功能
2006/10/13 Javascript
基于jQuery的history历史记录插件
2010/12/11 Javascript
删除节点的jquery代码
2014/01/13 Javascript
js点击事件链接的问题解决
2014/04/25 Javascript
jQuery实现左右切换焦点图
2015/04/03 Javascript
原生js制作简单的数字键盘
2015/04/24 Javascript
JavaScript事件详细讲解
2016/06/27 Javascript
使用JS正则表达式 替换括号,尖括号等
2016/11/29 Javascript
EditPlus中的正则表达式 实战(4)
2016/12/15 Javascript
JS高级运动实例分析
2016/12/20 Javascript
JavaScript仿微信(电话)联系人列表滑动字母索引实例讲解(推荐)
2017/08/16 Javascript
如何在JavaScript中优雅的提取循环内数据详解
2019/03/04 Javascript
express框架中使用jwt实现验证的方法
2019/08/25 Javascript
vue 的 solt 子组件过滤过程解析
2019/09/07 Javascript
vue使用echarts图表自适应的几种解决方案
2020/12/04 Vue.js
基于vue-simple-uploader封装文件分片上传、秒传及断点续传的全局上传插件功能
2021/02/23 Vue.js
使用python将mdb数据库文件导入postgresql数据库示例
2014/02/17 Python
Python计算程序运行时间的方法
2014/12/13 Python
利用python获取当前日期前后N天或N月日期的方法示例
2017/07/30 Python
python入门前的第一课 python怎样入门
2018/03/06 Python
python 以16进制打印输出的方法
2018/07/09 Python
python双向链表原理与实现方法详解
2019/12/03 Python
python入门:argparse浅析 nargs='+'作用
2020/07/12 Python
python如何爬取网页中的文字
2020/07/28 Python
美国顶尖折扣时尚购物网:Bluefly
2016/08/28 全球购物
优秀女职工事迹材料
2014/02/06 职场文书
2015年大学元旦晚会活动策划书
2014/12/09 职场文书
实习协议书
2015/01/27 职场文书
详解Node.js如何处理ES6模块
2021/05/15 Javascript