这篇文章给大家介绍Python垃圾回收机制原理是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
一。垃圾回收机制
Python中的垃圾回收是以引用计数为主,分代收集为辅。引用计数的缺陷是循环引用的问题。
在Python中,如果一个对象的引用数为0,Python虚拟机就会回收这个对象的内存。
#=utf - 8编码 时间=__author__ & # 39; kevinlu1010@qq.com& # 39; class ClassA (): ,,,def __init__(自我): ,,,,,,,print & # 39; object 出生,id: % & # 39; % str(十六进制(id(自我))) ,,,def __del__(自我): ,,,,,,,print & # 39; object 德尔,id: % & # 39; % str(十六进制(id(自我))) def f1 (): ,,,while 正确的: ,,,,,,,c1=ClassA () ,,,,,,,del c1
执行f1()会循环输出这样的结果,而且进程占用的内存基本不会变动
object 出生,x237cf58 id: 0 object 德尔,id: 0 x237cf58
<代码> c1=ClassA() 代码>会创建一个对象,放在<代码> 0 x237cf58> 代码内存中,c1变量指向这个内存,这时候这个内存的引用计数是1
<代码> del c1 代码>后,c1变量不再指向<代码> 0 x237cf58> 代码内存,所以这块内存的引用计数减一,等于0,所以就销毁了这个对象,然后释放内存。
- <李>
导致引用计数+ 1的情况
李>- <李>
对象被创建,例如<代码>=23日代码>
李> <李>对象被引用,例如<代码> b=代码>
李> <李>对象被作为参数,传入到一个函数中,例如<代码> func (a) 代码>
李> <李>对象作为一个元素,存储在容器中,例如<代码> list1=[,] 代码>
李>导致引用计数1的情况演示
def func (c, d): ,,,print & # 39; func 函数# 39;,拷贝,sys.getrefcount (c),安康;1 print & # 39; init # 39;,, sys.getrefcount(11),安康;1 a =11 print & # 39; after =11 & # 39;, sys.getrefcount(11),安康;1 b =, print & # 39; after b=1 & # 39;,, sys.getrefcount(11),安康;1 func (11) print & # 39; after  func (a) & # 39;,, sys.getrefcount(11),安康;1 list1 =,(,,, 12日14] print & # 39; after list1=(一个、12、14)& # 39;,,sys.getrefcount(11),安康;1=12 print & # 39; after =12 & # 39;, sys.getrefcount(11),安康;1 del print & # 39; after del 一个# 39;,,sys.getrefcount(11),安康;1 del b print & # 39; after del b # 39;,, sys.getrefcount(11),安康;1 #,list1.pop (0) #,print & # 39; after pop list1& # 39; sys.getrefcount (11) 1 del list1 print & # 39; after del  list1& # 39;,, sys.getrefcount(11),安康;1
输出:
init 24 after =11, 25岁 after b=1, 26岁 拷贝func function 28 after func (a), 26岁 after list1=(12、14), 27岁 after =12, 26岁 after del  a 26 after del  b 25 after del  list1 24
<强>问题:为什么调用函数会令引用计数+ 2 强>
李>- <李>
对象的别名被显式销毁,例如<代码> del 代码>
李> <李>对象的别名被赋予新的对象,例如<代码>=24 代码>
李> <李>一个对象离开它的作用域,例如f函数执行完毕时,func函数中的局部变量(全局变量不会)
李> <李>对象所在的容器被销毁,或从容器中删除对象
李>查看一个对象的引用计数
李><代码> sys.getrefcount (a)> 代码可以查看一个对象的引用计数,但是比正常计数大1,因为调用函数的时候传入,这会让一个的引用计数+ 1
二。循环引用导致内存泄露
def f2 (): ,,,while 正确的: ,,,,,,,c1=ClassA () ,,,,,,,c2=ClassA () ,,,,,,,c1.t=c2 ,,,,,,,c2.t=c1 ,,,,,,,del c1 ,,,,,,,del c2
执行f2(),进程占用的内存会不断增大。
object 出生,x237cf30 id: 0 object 出生,id: 0 x237cf58
创建了c1, c2后,<代码> 0 x237cf30> 代码(c1对应的内存,记为内存1),<代码> 0 x237cf58> 代码(c2对应的内存,记为内存2)这两块内存的引用计数都是1,执行<代码> c1.t=c2 代码>和<代码> c2.t c1=> 代码后,这两块内存的引用计数变成2。