Python 中的垃圾回收机制(Garbage Collection, GC)用于自动管理内存,回收不再使用的对象,以防止内存泄漏。Python 的垃圾回收机制主要依赖于引用计数(Reference Counting)和循环垃圾回收(Cycle Garbage Collection)两种策略。
引用计数(Reference Counting)
引用计数是 Python 内存管理的基础机制。每个对象都有一个引用计数器,记录有多少个引用指向该对象。当引用计数变为零时,说明该对象不再被使用,可以被回收。
示例代码
python复制
import sys
a = [] # 创建一个空列表对象
print(sys.getrefcount(a)) # 输出: 2,a 和 getrefcount 的参数都引用了这个列表
b = a # b 也引用了这个列表
print(sys.getrefcount(a)) # 输出: 3
del b # 删除 b 的引用
print(sys.getrefcount(a)) # 输出: 2
del a # 删除 a 的引用
# 此时引用计数为 0,列表对象会被回收
循环垃圾回收(Cycle Garbage Collection)
引用计数机制有一个主要的缺陷:它无法处理循环引用。循环引用是指对象之间相互引用,导致引用计数永远不会变为零。为了解决这个问题,Python 引入了循环垃圾回收机制。
循环垃圾回收器会定期检查对象图,寻找无法通过引用计数回收的循环引用对象,并将其回收。
示例代码
python复制
import gc
class Node:
def __init__(self, value):
self.value = value
self.next = None
# 创建循环引用
node1 = Node(1)
node2 = Node(2)
node1.next = node2
node2.next = node1
# 手动触发垃圾回收
gc.collect()
在这个示例中,node1 和 node2 互相引用,形成了一个循环引用。即使删除了 node1 和 node2 的引用,循环引用的对象也不会被引用计数机制回收。通过调用 gc.collect(),可以手动触发循环垃圾回收器来回收这些对象。
垃圾回收器的分代回收
Python 的垃圾回收器使用分代回收(Generational Garbage Collection)策略,将对象分为三代:
- 年轻代(Generation 0) :新创建的对象。
- 中生代(Generation 1) :从年轻代晋升的对象。
- 老年代(Generation 2) :从中生代晋升的对象。
垃圾回收器会更频繁地检查年轻代对象,因为这些对象更有可能很快变为垃圾。老年代对象则会较少被检查,因为它们更有可能是长期存活的对象。
控制垃圾回收
Python 提供了 gc 模块,允许你手动控制垃圾回收器的行为。
常用函数
gc.collect([generation]):手动触发垃圾回收。可以指定要回收的代数(0、1 或 2)。gc.get_threshold():获取垃圾回收的阈值。gc.set_threshold(threshold0, threshold1, threshold2):设置垃圾回收的阈值。gc.get_count():获取当前各代的对象数量。
示例代码
python复制
import gc
# 获取当前垃圾回收阈值
print(gc.get_threshold()) # 输出: (700, 10, 10)
# 设置新的垃圾回收阈值
gc.set_threshold(1000, 15, 15)
# 获取当前各代的对象数量
print(gc.get_count()) # 输出: (当前 Generation 0 的对象数, Generation 1 的对象数, Generation 2 的对象数)
# 手动触发垃圾回收
gc.collect()
总结
Python 的垃圾回收机制结合了引用计数和循环垃圾回收,以自动管理内存,防止内存泄漏。引用计数是基础机制,但无法处理循环引用;循环垃圾回收器则用于检测和回收循环引用的对象。通过 gc 模块,你可以手动控制和调试垃圾回收器的行为,以优化内存管理。理解这些机制有助于编写高效和健壮的 Python 程序。