Python 进行内存管理主要有两个机制:引用计数和垃圾回收。下面将详细讲解这两个机制。
引用计数
Python 中的每个对象都包含一个引用计数字段,表示当前有多少个指针指向该对象。当引用计数减为 0 时,表示该对象已经无法再被访问,可以被垃圾回收机制释放内存。
Python 的引用计数机制简单高效,但存在一个问题:循环引用。即两个或多个对象之间互相引用,导致它们的引用计数永远不会减为 0。例如:
lst1 = [1, 2, 3]
lst2 = [4, 5]
lst1.append(lst2)
lst2.append(lst1)
这时,lst1 和 lst2 彼此引用,它们的引用计数永远不会减为 0,导致内存泄露。
Python 增加了一个针对循环引用的垃圾回收机制。
垃圾回收
Python 中的垃圾回收机制是自动的,无需手动操作。它利用一个叫做“标记-清除”(mark and sweep)的算法,用于检测和清除不再使用的对象。
垃圾回收机制的主要过程如下:
-
首先,从 Root(根)对象(如全局变量)一步步遍历所有可达对象,标记(即打上标记)所有可达对象。
-
然后,扫描堆内存中所有的对象,清除(无标记)的对象所占用的内存,标记对象的标记清除,以备下次循环回收。
下面我们来看一个示例:
lst1 = [1, 2, 3]
lst2 = [4, 5]
lst1.append(lst2)
lst2.append(lst1)
del lst1
del lst2
在执行完 del lst1 和 del lst2 后,lst1 和 lst2 内部的对象仍然被引用,它们的引用计数不为 0。这时,垃圾回收机制会扫描内存中的对象,发现 lst1 和 lst2 对象已经不再被 Root 对象引用,标记它们为垃圾对象,并清除它们所占据的内存空间。
另一个示例是使用 weakref 模块:
import weakref
class MyClass:
pass
my_class = MyClass()
my_ref = weakref.ref(my_class)
print(my_ref()) # 根据弱引用获取对象
del my_class
print(my_ref()) # 弱引用对应的对象已经被回收,返回 None
在这个示例中,使用 weakref 模块创建一个弱引用对象 my_ref。当 my_ref 所引用的对象(my_class)被回收后,my_ref() 调用将返回 None。
以上是 Python 进行内存管理的完整攻略,包含引用计数和垃圾回收两个机制的详细讲解,并给出了两个示例。