Garbage Collection(垃圾回收)

gc

Garbage Collection

  Garbage Collection(GC,垃圾回收):不是Python特有的,而是现在许多高级语言自带的机制,可以帮助我们更高效的管理我们的内存,在C/C++的学习过程中,最重要的两个部分是指针和内存管理,其中内存管理就是指垃圾回收机制,在C/C++中,无法自动帮我们管理内存,如果我们缺少内存则需要申请,但是申请多了会导致内存不足,这时候需要我们手动释放一些内存。但是在Python中不需要,系统会自动帮我们释放内存,这个知识点不需要我们熟练掌握,只需要我们了解即可,运行代码时会自动启用垃圾回收机制。

小整数对象池

因为一些小整数会被我们经常使用,所以在Python中[-5, 256]之间的整数会被固定在某一内存中,只要是这些整数赋值给某一变量,则那个变量的地址是固定的。在字符串中也有相似的表现,没有特殊字符的字符串也具有固定的地址
gc1

引用计数

Python里每一个东西都是对象,它们的核心就是一个结构体:PyObject,是使用C语言来定义的

1
2
3
4
typedef struct_object {
int ob_refcnt;
struct_typeobject *ob_type;
} PyObject;

其中ob_refcnt就是引用计数,当一个对象有新的引用时,这个值会增加,当引用它的对象被删除时,这个值会减少,使用sys.getrefcount()函数可以查看对象的引用计数。当引用计数为0时,该对象的生命就结束了

导致引用计数增加的情况

  1. 对象被创建
  2. 对象被引用
  3. 对象作为参数被传入到一个函数中
  4. 对象作为元素,存储在容器中

导致引用计数减少的情况

  1. 对象被销毁
  2. 对象被赋予新的对象
  3. 对象离开作用域
  4. 对象所在容器被销毁

gc2
为什么创建时引用为2呢?因为调用sys.getrefcount(a)时,a作为参数传入到函数中,引用计数又加了1,所以sys,getrefcount()-1才是真正的引用计数次数。

引用计数的优点

  1. 简单
  2. 实时性,当引用计数为0,内存直接释放

引用计数的缺点

  1. 需要一个额外的内存存放引用计数
  2. 存在循环引用的致命缺点
1
2
3
4
5
6
7
8
9
class MyClass:
pass

a = MyClass()
b = MyClass()
a.next = b
b.next = a
del a
del b

a和b我们都已经不想使用了,因此使用了del,但是a和b的引用计数都为1,内存仍然没有被释放,这就是循环引用的致命缺点,会导致内存的严重泄漏

隔代回收

在这里不想过多的探讨隔代回收,简单地说Python中会引入3个链表,所有新创建的对象都会加入到0代链表中,在一定的时间内检查并且扫描所有的循环引用,如果发现了两个对象的循环引用,则将引用计数-1,并且将0代链表中引用计数不为0的对象加入到1代链表中,当0代链表检查一定次数后,检查一次1代链表,重复上述动作,并将1代链表中引用计数不为0的对象加入到2代链表中,当1代链表检查一定次数后,检查一次2代链表。这就是隔代回收的大致思路。
gc3

小结

  关于垃圾回收,不需要小伙伴们过多掌握,Python中默认开启垃圾回收机制,小伙伴们只要适当了解,就可以愉快的写代码啦。

-------------本文结束感谢您的阅读-------------
0%