聊一聊 Python 对象的「垃圾收集」那些事儿。

时间:2022-06-23
本文章向大家介绍聊一聊 Python 对象的「垃圾收集」那些事儿。,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

00.写在之前

有时候写代码玩,懒得去想变量名的时候,你可能会做出下面这样的举动:

>>> a = 1
>>> a = 2.0
>>> a = 'Rocky'

虽然可能看着有些奇怪,a 刚开始是个整数,然后又变成了浮点数,最后变成了一个字符串,但它确实是可行的,这个也符合我在上篇文章 浅谈动态类型领域中 Python 的变量、对象以及引用。 中所说的「变量本身就是通用的,它只是恰巧在某个时间点上引用了当时的特定对象而已」。

同样我在上一篇文章中也说过在 Python 内部是「变量引用对象」,我不知道大家在看到上面的代码时脑袋里有没有产生过这么一个疑问:当我重新给变量 a 赋值的时候,它的前一个引用值去哪了?也就是当我给 a 重新赋值为 2.0 的时候,1 这个值去哪了?

答案是每当一个变量被重新赋予一个新的对象,如果之前的对象没有被其他变量名或者对象引用的话,那么之前的对象所占用的空间就会被回收。这种自动回收对象空间的做法就叫对象的「垃圾收集」。

01.垃圾收集

为了更好的搞明白,我们还是用上面说过的那个例子:

>>> a = 1
>>> a = 2.0
>>> a = 'Rocky'

上面的例子中,a 每次都是被设置成了不同类型的对象,尽管我们心知这不是真正的情况,但达成的效果却是变量的类型每次都在改变,这种代码行得通的原因还是我无数次强调过的:「类型属于的是对象,不是变量,变量只是引用了对象而已」。

在重新赋值的过程中,变量是引用了新的对象,旧的对象在此过程中一个一个的被丢弃,Python 回收了它们的空间。比如说,当 a 赋值为 2.0 的时候,对象 1 如果没有被其他对象引用的话,它就会马上被回收,空出来的空间自动放入自由内存空间池,等待着后来者使用。

可能到这你会有这个问题,Python 怎么知道一个对象又没有被其它对象引用呢?这个就需要我们来探究 Python 内部是怎样来实现这个功能的,其实也没什么大不了的,就是是靠一个叫「计数器」的东西。

Python 在每个对象中放了一个计数器,计数器记录的是当前指向这个对象的引用数目,一旦这个计数器成了零,这个对象的所在的内存空间就会被自动回收。在上述例子中,a 每次都被赋值给一个新的对象,而旧对象的计数器成了零,从而旧对象的空间被回收掉。

02.写在之后

从「垃圾回收」其实也可以看出动态语言对比静态语言的“省心”,Python 程序运行的时候会清理掉不用的内存空间,这就意味着我们可以在写的代码中“任性”的使用对象(当然这个做法不推荐)而不需要去考虑释放内存空间这种“烦心事”,这样相比 C 或者 C++ 来说,可以偷懒少写不少东西。