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

二、标记清除

三、分代

四、缓存

相关