python垃圾回收机制主要分为:
1. 引用计数
2. 标记清除
3. 分代回收
python的引用计数机制:
python是根据对象的引用计数是否为0,来进行垃圾回收,释放内存的
引用计数增加的几种情况:
1、对象创建被赋值给变量
2、对象被其他的变量引用(引用它的变量赋值给了其他变量)
3、当对象被当成参数传入函数中
4、对象被放到其他的容器中(或者保存为其他对象的属性)
引用计数减少的几种情况:
1、保存对象的变量被删除
2、引用该对象的变量被重新赋值,引用了其他的对象
3、被当成函数参数传入函数中,当函数调用结束
4、对象从容器中删除(保存对的属性被删除)
sys.getrefcount查看当前序列的的引计数:
import sys a = {"aa": 1} b = a c = [11, 22, a] print("1查看对象的引用计数:", sys.getrefcount(b)) # 1查看对象的引用计数: 4
sys.getrefcount查看int整数str类型的引计数:
a = 0 b = "a" print("查看对象a的引用计数:", sys.getrefcount(a)) print("查看对象b的引用计数:", sys.getrefcount(b)) 结果: 查看对象a的引用计数: 174 查看对象b的引用计数: 9
分析当中结果: 我们当前a和b只引用了两次为什么引计数不是2呢?这是因为当前的python针对长引用的值做了对应的优化处理
那就是 小整数池,和字符串驻留池
小整数池:
1、小整数池:
对象咱们python中 -5 到256之间的整数,python做了优化处理
在运行python程序时,python会自动将开辟一块内存将-5 到256之间的整数对象全部创建好,加入一个小整数池中
意义:为了避免python程序频繁申请内存和回收释放内存,对于常用的整数(-5 到256)python开发团队而设计的优
化机制,在引用这些整数的过程当中,会直接去小整数池当中取值,
例: 可以看到 a和b的值都是5,打印的内存都是同一个值.
a = 5 b = 5 print(id(a),id(b)) # 结果: 2064409760 2064409760
2、字符串驻留池:
对于python程序中 纯单词字符(数字、字母、下划线)组成的字符串,python也进行了优化
在运行python程序时,创建纯单词字符组成的字符串会加入到字符串驻留池中,当再次创建相同的字符串时,直接
引用字符串驻留池中的
例: 可以看到 a和b的值都是"abc",打印的内存都是同一个值.
a = "abc" b = "abc" print(id(a),id(b)) # 结果: 30597984 30597984
标记清除:
引用计数存在一个缺点那就是当两个对象出现循环引用的时候,
那么这个两个变量始终不会被销毁,这样就会导致内存泄漏,
标记清除就是为了解决上述循环引用的情况
#第一组循环引用# a = [1,2] b = [3,4] a.append(b) b.append(a) del a
标记清除: 他先划分出两拨,一拨叫(存活组),一拨叫死亡组)。然后,他把各个对象的引用计数复制出来,对这个副本进行引用环的摘除。
分代回收:import gc print(gc.get_threshold()) 可以通过gc模块来看下分代回收的机制: 输出结果:(700,10,10)
1.在回收的过程当中也是通过标记的方法,将需要被删除的垃圾放入回收链表进行pyhton的垃圾回收
2.在python当中并不是一直循环去回收垃圾的,而是通过分代回收总共分为三个链表容器: 当第0代链表的对象达到700个对象的时候,python 开始回收垃圾,一些还被引用的数,则放入下一个链表容器当中,当第零代链表执行10次之后,第一代链表开始进行回收垃圾,未被回收的垃圾 则放入第二代链表当中,当第一代链表容器回收10次之后我第二代链表开始回收操作.标签:python,回收,链表,计数,对象,垃圾,引用 From: https://www.cnblogs.com/manxingsir/p/16896594.html