python垃圾回收
写在开头:
永远记住一句话:引用计数为主,标记清除和分代为辅+缓存
本节内容:
1:引用计数器
2:标记清除
3:分代
4:缓存
https://pythonav.com/wiki/detail/6/88/
一、引用计数器
1.1:环状双向链表
在讲Python回收的时候,我们先讲一讲Python如果创建了一个对象name="python"这个对象会放到哪里去?
划重点:在Python程序中如果创建了任何对象都会放到一个神奇的狗链子中去-叫做refchain环状双向链表中去。
在上面的图片中,我们创建一个"武沛齐"的字符串对象和整型的18对象,这些对象都放到这条狗链子中去。
那么有个问题,放进去的对象有什么特点吗?为什么可以变成一个环?
我们查看Python的C语言源码的时候,可以发现。
比如在创建一个float数据结构时候的时候,他的对象内部是会保存这些值:
typedef struct {
PyObject_HEAD //这对象是
double ob_fval; //这是对象的值
} PyFloatObject;
Python在创建对象的时候,对象内部会他们都会保存上一个对象的地址以及下一个对象的地址,这样他们之间就可以用环链接起来了。
创建了float类型的时候,除了上一个和下一个的地址外,还会保存这个对象的引用计数器,以及这个对象的类型。
1.2:引用计数器实现
我们知道了创建一对象会放到refchain的环状双向链表,以及这个对象内部会保存上一个和下一个的地址、引用计数器、对象类型。
在创建float的时候是保存这些的,如果创建字符串或者列表的时候他会额外保存一些东西。比如字典他还会保存key、value 。列表还是保存元素的个数。
age = 18 name = "武沛齐" nickname = name
上述代码表示内存中有 18 和 “武沛齐” 两个值,他们的引用计数器分别为:1、2 。
当值被多次引用时候,不会在内存中重复创建数据,而是引用计数器+1 。 当对象被销毁时候同时会让引用计数器-1,
如果引用计数器为0,则将对象从refchain链表中摘除,同时在内存中进行销毁(暂不考虑缓存等特殊情况)。
age = 18
number = age # 对象18的引用计数器 + 1
del age # 对象18的引用计数器 - 1
def run(arg):
print(arg)
run(number) # 刚开始执行函数时,对象18引用计数器 + 1,当函数执行完毕之后,对象18引用计数器 - 1 。
num_list = [11,22,number] # 对象18的引用计数器 + 1