阅读 4697

【译】Python 内存管理之垃圾回收

Python 内存管理之垃圾回收

Artwork created by [Katerina Limpitsouni](https://twitter.com/ninalimpi)

如果您已经编码过一段时间,那么您可能听说过垃圾回收。在本文中,我们将更深入地研究它的功能和原理。

What 和 Why

在现实世界中,我们会清理掉一些东西 —— 例如旧笔记,不再需要的盒子 —— 将它们丢弃在垃圾桶或者回收箱中。因为存储的空间有限,所以我们要为其它重要的物品腾出存储空间。

同样地,在计算机中,空间 —— 也称为内存是重要且有限的资源。因此,垃圾回收器会收集不再需要的数据对象并将其丢弃。

垃圾回收可以是自动的也可以是手动的,它取决于不同的编程语言。在大多数高级语言(例如 Python 和 Java)中,它是自动的。因此,这些语言称为垃圾回收语言。其它语言(例如 C)不支持自动垃圾回收,程序员负责内存管理。

下面我们来看看垃圾回收的原理。

How

垃圾回收原理中有一些不同的技术,但大多数垃圾回收语言(包括 Python)都使用引用计数。在引用计数中,我们记录对象的引用数,并在计数为 0 时丢弃对象。

对象的引用计数随着指向该对象的别名数量的变化而变化。给对象分配新名称或将其放置在列表或字典等容器中时,引用计数会增加。当使用 del 命令删除对象,引用超出范围或重新分配对象时,计数会减少。例如:

sample = 100 # 创建 <100> 对象,引用计数 = 1。

sample_copy = sample # 引用计数 = 2. 

sample_list = [sample] # 引用计数 = 3.

del sample # 引用计数 = 2。注意这里不会影响 sample_copy 和 sample_list,因为它们直接指向 <100>。
sample_copy = 10 # 引用计数 = 1,因为变量重新分配了。

sample_list.clear() # 引用计数 = 0,当 list 清空后就不会存储指向 <100> 的变量了。
复制代码

当引用计数下降到 0 时,对象会被立即回收。但是这样做有一个代价:我们需要为每个对象存储一个附加的整数值,以指示其引用计数(空间与时间的权衡)。

但是,引用计数系统中存在 循环引用 的问题。如果两个对象 A 和 B 互相引用,则它们的引用计数将会始终大于或等于 1。这种情况在列表、类和函数中很常见。例如,当对象引用自身时:

x = []
x.append(x)
复制代码

或者当对象相互引用时:

a.attribute_1 = b
b.attribute_2 = a
复制代码

垃圾回收器会定期找出循环引用并将其删除。这个过程会耗费昂贵的资源,所以它是定期执行的并且是可计划的。Python 中的垃圾回收器接口提供了一些方法,您可以用它们来探索执行垃圾回收的计划和阈值。

gc - 垃圾回收器接口 - Python 3.8.3rc1 文档


结论

希望本文能帮到你。 请进一步阅读以下参考资料:

如果发现译文存在错误或其他需要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可获得相应奖励积分。文章开头的 本文永久链接 即为本文在 GitHub 上的 MarkDown 链接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

文章分类
后端