0

0

Python 内存管理的工作原理,你了解吗?

WBOY

WBOY

发布时间:2023-04-12 16:25:09

|

1422人浏览过

|

来源于51CTO.COM

转载

Python 为开发者提供了许多便利,其中最大的便利之一是其几乎无忧的内存管理。开发者无需手动为 Python 中的对象和数据结构分配、跟踪和释放内存。运行时会为你完成所有这些工作,因此你可以专注于解决实际问题,而不是争论机器级细节。

Python 内存管理的工作原理,你了解吗?

尽管如此,即使是经验不多的 Python 用户,了解 Python 的垃圾收集和内存管理是如何工作的也是有好处的。了解这些机制将帮助你避免更复杂的项目可能出现的性能问题。你还可以使用 Python 的内置工具来监控程序的内存管理行为。

Python如何管理内存

每个 Python 对象都有一个引用计数,也称为引用计数。 refcount 是持有对给定对象的引用的其他对象总数的计数。当你添加或删除对对象的引用时,数字会上升或下降。当一个对象的引用计数变为零时,该对象将被释放并释放其内存。

什么是参考?允许通过名称或通过另一个对象中的访问器访问对象的任何内容。

这是一个简单的例子:

x = "Hello there"

当我们向 Python 发出这个命令时,引擎盖下会发生两件事:

  1. 该字符串"Hello there"作为 Python 对象创建并存储在内存中。
  2. 该名称x在本地命名空间中创建并指向该对象,这会将其引用计数增加 1 到 1。

如果我们说y = x,那么引用计数将再次提高到 2。

每当xandy超出范围或从它们的命名空间中删除时,对于每个名称,字符串的引用计数都会减少 1。一旦x和y都超出范围或被删除,字符串的引用计数变为 0 并被删除。

现在,假设我们创建了一个包含字符串的列表,如下所示:

x = ["Hello there", 2, False]

字符串保留在内存中,直到列表本身被删除或包含字符串的元素从列表中删除。这些操作中的任何一个都将导致唯一持有对字符串的引用的事物消失。

现在考虑这个例子:

x = "Hello there" y = [x]

如果我们从 中删除第一个元素y,或者完全删除列表y,则字符串仍在内存中。这是因为名称x包含对它的引用。

Python 中的引用循环

在大多数情况下,引用计数工作正常。但有时你会遇到两个对象各自持有对彼此的引用的情况。这称为 参考周期。在这种情况下,对象的引用计数永远不会达到零,也永远不会从内存中删除。

这是一个人为的例子:

x = SomeClass()
y = SomeOtherClass()
x.item = y
y.item = x

由于x并y持有彼此的引用,因此它们永远不会从系统中删除——即使没有其他任何东西引用它们中的任何一个。

Python 自己的运行时为对象生成引用循环实际上是相当普遍的。一个示例是带有包含对异常本身的引用的回溯对象的异常。

在Python的早期版本中,这是一个问题。具有引用周期的对象可能会随着时间的推移而累积,这对于长时间运行的应用程序来说是一个大问题。但 Python 此后引入了循环检测和垃圾收集系统,用于管理引用循环。

Python 垃圾收集器 (gc)

Python 的垃圾收集器检测具有引用周期的对象。它通过跟踪作为“容器”的对象(例如列表、字典、自定义类实例)并确定其中的哪些对象无法在其他任何地方访问来实现这一点。

一旦这些对象被挑选出来,垃圾收集器就会通过确保它们的引用计数可以安全地降为零来删除它们。

绝大多数 Python 对象没有引用周期,因此垃圾收集器不需要 24/7 运行。相反,垃圾收集器使用一些启发式方法来减少运行频率,并且每次都尽可能高效地运行。

当 Python 解释器启动时,它会跟踪已分配但未释放的对象数量。绝大多数 Python 对象的生命周期都很短,因此它们会迅速出现和消失。但随着时间的推移,更多长寿的物体会出现。一旦超过一定数量的此类对象堆积起来,垃圾收集器就会运行。

每次垃圾收集器运行时,它都会收集所有在收集中幸存下来的对象,并将它们放在一个称为一代的组中。这些“第一代”对象在参考周期中被扫描的频率较低。任何在垃圾收集器中幸存下来的第一代对象最终都会迁移到第二代,在那里它们被扫描得更少。

小羊标书
小羊标书

一键生成百页标书,让投标更简单高效

下载

同样,垃圾收集器不会跟踪所有内容。例如,像用户创建的类这样的复杂对象总是被跟踪。但是不会跟踪仅包含简单对象(如整数和字符串)的字典,因为该特定字典中的任何对象都不会包含对其他对象的引用。不能保存对其他元素(如整数和字符串)的引用的简单对象永远不会被跟踪。

如何使用 gc 模块

通常,垃圾收集器不需要调整即可运行良好。Python 的开发团队选择了反映最常见现实世界场景的默认值。但是如果你确实需要调整垃圾收集的工作方式,你可以使用Python 的 gc 模块。该gc模块为垃圾收集器的行为提供编程接口,并提供对正在跟踪的对象的可见性。

gc当你确定不需要垃圾收集器时,你可以做的一件有用的事情是关闭它。例如,如果你有一个堆放大量对象的短运行脚本,则不需要垃圾收集器。脚本结束时,所有内容都将被清除。为此,你可以使用命令禁用垃圾收集器gc.disable()。稍后,你可以使用 重新启用它gc.enable()。

你还可以使用 手动运行收集周期gc.collect()。一个常见的应用是管理程序的性能密集型部分,该部分会生成许多临时对象。你可以在程序的该部分禁用垃圾收集,然后在最后手动运行收集并重新启用收集。

另一个有用的垃圾收集优化是gc.freeze(). 发出此命令时,垃圾收集器当前跟踪的所有内容都被“冻结”,或者被列为免于将来的收集扫描。这样,未来的扫描可以跳过这些对象。如果你有一个程序在启动之前导入库并设置大量内部状态,那么你可以gc.freeze()在所有工作完成后发出。这使垃圾收集器不必搜寻那些无论如何都不太可能被删除的东西。(如果你想对冻结的对象再次执行垃圾收集,请使用gc.unfreeze().)

使用 gc 调试垃圾收集

你还可以使用它gc来调试垃圾收集行为。如果你有过多的对象堆积在内存中并且没有被垃圾收集,你可以使用gc's 检查工具来找出可能持有对这些对象的引用的对象。

如果你想知道哪些对象持有对给定对象的引用,可以使用gc.get_referrers(obj)列出它们。你还可以使用gc.get_referents(obj)来查找给定对象引用的任何对象。

如果你不确定给定对象是否是垃圾收集的候选对象,gc.is_tracked(obj)请告诉你垃圾收集器是否跟踪该对象。如前所述,请记住垃圾收集器不会跟踪“原子”对象(例如整数)或仅包含原子对象的元素。

如果你想亲自查看正在收集哪些对象,可以使用 设置垃圾收集器的调试标志gc.set_debug(gc.DEBUG_LEAK|gc.DEBUG_STATS)。这会将有关垃圾收集的信息写入stderr。它将所有作为垃圾收集的对象保留在只读列表中。

避免 Python 内存管理中的陷阱

如前所述,如果你在某处仍有对它们的引用,则对象可能会堆积在内存中而不会被收集。这并不是 Python 垃圾收集本身的失败。垃圾收集器无法判断你是否不小心保留了对某物的引用。

让我们以一些防止对象永远不会被收集的指针作为结尾。

注意对象范围

如果你将对象 1 指定为对象 2 的属性(例如类),则对象 2 将需要超出范围,然后对象 1 才会:

obj1 = MyClass()
obj2.prop = obj1

更重要的是,如果这种情况发生在某种其他操作的副作用中,例如将对象 2 作为参数传递给对象 1 的构造函数,你可能不会意识到对象 1 持有一个引用:

obj1 = MyClass(obj2)

另一个例子:如果你将一个对象推入模块级列表并忘记该列表,则该对象将一直保留,直到从列表中删除,或者直到列表本身不再有任何引用。但是如果该列表是一个模块级对象,它可能会一直存在,直到程序终止。

简而言之,请注意你的对象可能被另一个看起来并不总是很明显的对象持有的方式。

使用 weakref避免引用循环

Python 的 weakref 模块允许你创建对其他对象的弱引用。弱引用不会增加对象的引用计数,因此只有弱引用的对象是垃圾回收的候选对象。

一个常见的用途weakref是对象缓存。你不希望仅仅因为它具有缓存条目而保留引用的对象,因此你将 aweakref用于缓存条目。

手动中断参考循环

最后,如果你知道给定对象包含对另一个对象的引用,你总是可以手动中断对该对象的引用。例如,如果你有instance_of_class.ref = other_object,你可以设置instance_of_class.ref = None何时准备删除 instance_of_class。

通过了解 Python 内存管理的工作原理,我们对其垃圾收集系统如何帮助优化 Python 程序中的内存,以及如何使用标准库和其他地方提供的模块来控制内存使用和垃圾收集。

原文标题:​​Python garbage collection and the gc module​

相关文章

python速学教程(入门到精通)
python速学教程(入门到精通)

python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

761

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1570

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

651

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1249

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

1206

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

194

2025.07.29

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

131

2025.08.07

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

90

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5万人学习

SciPy 教程
SciPy 教程

共10课时 | 2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号