Python中的垃圾回收是什么?

2025年1月5日 | 阅读6分钟

引言

在Python中,垃圾回收(Garbage Collection, GC)是一种自动内存管理功能,通过释放不再使用的对象所占用的内存来优化资源使用。Python通过引用计数和循环垃圾收集器来查找和删除不必要的对象。当对象的引用计数变为零时,内存就会被释放,这个过程称为引用计数。另一方面,循环垃圾收集器会查找并打破对象中存在的引用循环,从而释放内存。通过动态控制内存的分配和释放,GC提高了效率,并使开发人员能够专注于应用程序逻辑,而不是内存管理。

自动循环垃圾回收

使用Python的代际垃圾回收(Generational Garbage Collection),对象被分为三个年龄组:年轻代、中年代和老年代。由于大多数对象都是短暂的,年轻代是新对象的来源,并会定期被收集。能够通过几次回收的对象会被提升到老年代,它们被收集的可能性较低。通过专注于最近创建的对象并减少频繁的全局堆搜索的负担,这种方法最大限度地提高了效率。代际模型利用了大多数对象很快就会被丢弃的经验法则,通过优先清理最临时的对象来有效地管理内存。

示例

输出

References to node1: []
References to node2: []

垃圾回收后,`gc.get_referrers(node1)` 返回一个空列表 `[]`,表示不再有对 `node1` 的引用。

类似地,`gc.get_referrers(node2)` 显示一个空列表 `[]`,表示在垃圾回收后,不再有对 `node2` 的引用。

说明

代码使用循环引用生成了两个 `Node` 对象(`node1.next` 指向 `node2`,反之亦然)。在创建对象后,显式调用垃圾收集器 (`gc.collect()`) 来回收内存。垃圾回收后,对节点1或节点2不再有任何引用,如 `gc.get_referrers(node1)` 和 `gc.get_referrers(node2)` 返回的空列表所示。这表明Python的循环垃圾收集器成功地找到并打破了循环引用,实现了对相关对象的有效内存清理。

手动垃圾回收

在Python和其他编程语言中,“自动循环垃圾回收”是指系统通过识别和释放被循环引用占用的内存来自动维护内存。“循环引用”是指两个或多个对象相互之间直接或间接引用,形成一个无法通过简单的引用计数来消除的循环。为了确保内存的有效利用,Python使用循环垃圾收集器,它会定期扫描内存以查找并打破这些循环。在此过程中,对象根据其存在时间被分为不同的代,年轻的对象会被更频繁地收集。通过自动化循环检测和清理,Python的垃圾回收系统有助于最大限度地减少内存泄漏并优化内存使用。这使得开发人员可以专注于应用程序逻辑,而不是繁琐的内存管理任务。

示例

输出

End of program
Deleting Honda car
Deleting Toyota car

说明

这个Python应用程序演示了循环引用对象的销毁和自动垃圾回收。它定义了一个名为 `Car` 的类,该类的实例有一个打印删除通知的 `__del__()` 函数和一个 `brand` 属性。代码使用循环引用来生成并连接两个 `Car` 对象,`car1`(丰田)和 `car2`(本田)(`car1.other_car = car2` 并且反之亦然)。在删除直接引用(`del car1`, `del car2`)并从代码中调用 `gc.collect()` 后,Python的垃圾收集器会识别并打破循环引用。当这个过程为每个车辆对象调用 `__del__()` 函数时,会打印出“正在删除本田汽车”和“正在删除丰田汽车”的消息。程序最后打印“程序结束”,以展示Python通过自动垃圾回收有效管理内存的能力。

强制垃圾回收

强制垃圾回收的编程术语描述了立即调用垃圾收集器来回收被未使用的对象占用的内存。在Python等语言中,可以通过使用 `gc` 模块中的 `gc.collect()` 函数来实现。虽然强制垃圾回收在需要即时内存清理的情况下可能很有用,例如在内存密集型操作之前释放空间,或者在需要可预测内存管理的实时系统中,但自动垃圾回收是周期性运行的。通过让开发人员控制内存释放的时间,它可以提高效率和性能。然而,由于强制内存清理需要更多的处理,并且可能导致性能下降,应避免频繁使用。

示例

输出

Unreachable objects collected: 0
End of program

说明

提供的Python脚本创建了一个内存占用率很高的巨大对象实例(`LargeObject`)来演示强制垃圾回收。在删除该对象的引用(`del large_object`)后,使用 `gc.collect()` 立即启动垃圾回收。在引用计数清理对象后,报告收集到的不可达对象数量,通常为0。最后,脚本输出“程序结束”,这表明了Python可以通过强制垃圾回收实现显式的内存管理和资源回收。尤其是在内存密集型过程之前,这保证了有效的内存利用。

禁用垃圾回收

禁用Python的自动内存管理系统可以为开发人员提供手动控制内存释放时间和方式的权限。在处理受控环境中的资源或在需要避免垃圾回收开销的性能关键型应用程序中,这可能很有帮助。Python提供了 `gc` 模块,其中包含 `gc.enable()`(重新启用垃圾回收)和 `gc.disable()`(关闭垃圾回收)等函数。虽然在某些情况下关闭垃圾回收可以提高速度,但这样做需要仔细管理,以避免内存泄漏并确保对象得到妥善处理,因为自动识别和清理不需要的对象不再有效。

示例

输出

End of program

说明

在提供的Python示例中,使用 `gc.disable()` 显式禁用了垃圾回收,即使在删除对象的引用(`del obj1`, `del obj2`)后,Python也不会自动回收对象的内存。这阻止了在对象删除时立即调用 `__del__()` 析构函数。因此,尽管创建了 `MyClass` 的实例(`obj1` 和 `obj2`)并删除了它们的引用,程序最后只打印了“程序结束”消息。使用 `gc.enable()` 启用垃圾回收会恢复自动内存管理,允许Python在后续操作中从未使用过的对象中回收内存。这种方法为开发人员提供了手动控制内存管理的能力,适用于需要精确资源处理或在Python应用程序中进行性能优化的场景。

优点

1. 自动内存管理

Python垃圾回收器会自动删除不再被引用的对象,以防止内存泄漏并降低内存耗尽的可能性。

Python通过垃圾回收器消除了开发人员手动管理内存的需要,使他们能够专注于编写代码,从而使其成为一种更高级、对开发人员更有用的语言。

2. 有效的内存清理

代际垃圾回收是垃圾回收器的一项功能,它通过快速识别和收集生命周期有限的对象来最大限度地减少性能影响。

3. 可配置的设置

开发人员可以使用垃圾回收器的可自定义设置功能,根据其特定的应用程序需求来微调垃圾回收过程,包括能够更改不同代阈值的能力。

缺点

1. 性能影响

即使垃圾回收器被设计成能够有效地清除不必要的内存,仍然可能存在一些CPU使用和执行时间开销,尤其是在处理大量对象时。

2. 管理内存的挑战

Python的垃圾回收器简化了内存管理,但要有效地使用它,可能仍然需要理解对象生命周期、对象引用和垃圾回收算法等概念。

3. 对内存管理的有限控制

由于垃圾回收器的自主性,它为开发人员提供了对内存清理确切时间和行为的最小控制,这可能不适用于许多需要细粒度内存管理控制的应用程序场景。