Garbage Collection
Garbage Collection(GC,垃圾回收):不是Python特有的,而是现在许多高级语言自带的机制,可以帮助我们更高效的管理我们的内存,在C/C++的学习过程中,最重要的两个部分是指针和内存管理,其中内存管理就是指垃圾回收机制,在C/C++中,无法自动帮我们管理内存,如果我们缺少内存则需要申请,但是申请多了会导致内存不足,这时候需要我们手动释放一些内存。但是在Python中不需要,系统会自动帮我们释放内存,这个知识点不需要我们熟练掌握,只需要我们了解即可,运行代码时会自动启用垃圾回收机制。
小整数对象池
因为一些小整数会被我们经常使用,所以在Python中[-5, 256]之间的整数会被固定在某一内存中,只要是这些整数赋值给某一变量,则那个变量的地址是固定的。在字符串中也有相似的表现,没有特殊字符的字符串也具有固定的地址。
引用计数
Python里每一个东西都是对象,它们的核心就是一个结构体:PyObject,是使用C语言来定义的。
1 | typedef struct_object { |
其中ob_refcnt就是引用计数,当一个对象有新的引用时,这个值会增加,当引用它的对象被删除时,这个值会减少,使用sys.getrefcount()函数可以查看对象的引用计数。当引用计数为0时,该对象的生命就结束了。
导致引用计数增加的情况:
- 对象被创建
- 对象被引用
- 对象作为参数被传入到一个函数中
- 对象作为元素,存储在容器中
导致引用计数减少的情况:
- 对象被销毁
- 对象被赋予新的对象
- 对象离开作用域
- 对象所在容器被销毁
为什么创建时引用为2呢?因为调用sys.getrefcount(a)时,a作为参数传入到函数中,引用计数又加了1,所以sys,getrefcount()-1才是真正的引用计数次数。
引用计数的优点:
- 简单
- 实时性,当引用计数为0,内存直接释放
引用计数的缺点:
- 需要一个额外的内存存放引用计数
- 存在循环引用的致命缺点
1 | class MyClass: |
a和b我们都已经不想使用了,因此使用了del,但是a和b的引用计数都为1,内存仍然没有被释放,这就是循环引用的致命缺点,会导致内存的严重泄漏。
隔代回收
在这里不想过多的探讨隔代回收,简单地说Python中会引入3个链表,所有新创建的对象都会加入到0代链表中,在一定的时间内检查并且扫描所有的循环引用,如果发现了两个对象的循环引用,则将引用计数-1,并且将0代链表中引用计数不为0的对象加入到1代链表中,当0代链表检查一定次数后,检查一次1代链表,重复上述动作,并将1代链表中引用计数不为0的对象加入到2代链表中,当1代链表检查一定次数后,检查一次2代链表。这就是隔代回收的大致思路。
小结
关于垃圾回收,不需要小伙伴们过多掌握,Python中默认开启垃圾回收机制,小伙伴们只要适当了解,就可以愉快的写代码啦。