Python教程:深入了解Python垃圾回收机制

1. 简介


在Python中,垃圾回收(Garbage Collection)是一种自动管理内存的机制,它可以自动识别和清理不再使用的对象,释放它们占用的内存空间,以提高内存利用率和程序性能。

2. 引用计数


引用计数是一种简单且高效的垃圾回收机制,它通过记录对象被引用的次数来管理内存。每当一个对象被引用,其引用计数加一;当对象的引用被删除或者失效时,引用计数减一。当引用计数为零时,代表没有任何引用指向该对象,因此可以安全地释放该对象所占用的内存空间。

import sys# 创建一个对象
x = [1, 2, 3]# 查看对象的引用计数
print(sys.getrefcount(x))  # 输出:2,因为getrefcount()本身也会增加一个引用

3. 循环引用


循环引用指的是两个或多个对象相互引用,导致它们的引用计数永远不会变为零,从而无法被垃圾回收。这种情况会造成内存泄漏,因为即使对象不再被程序使用,但由于循环引用导致的引用计数不为零,垃圾回收器也无法释放这些对象占用的内存空间。

import gc# 创建循环引用
x = [1, 2, 3]
y = [4, 5, 6]
x.append(y)
y.append(x)# 显示循环引用的对象
print(gc.get_referrers(x))  # 输出:[[[1, 2, 3], [4, 5, 6]]]
print(gc.get_referrers(y))  # 输出:[[[1, 2, 3], [4, 5, 6]]]

4. 标记-清除算法


标记清除算法是一种基于对象可达性的垃圾回收算法。它通过从根对象(如全局变量、活动函数等)出发,标记所有能够被引用到的对象,然后清除未标记的对象。这样就能够释放那些不再被引用的对象占用的内存空间。

# 手动触发标记-清除算法
gc.collect()

5. 分代回收


分代回收是一种高效的垃圾回收策略,通常应用于长时间运行的程序中,如服务器端应用或长期运行的桌面应用。它的核心思想是基于对象的生命周期将内存分为不同的代(Generation),并针对每一代采取不同的回收策略。

一般来说,程序中的对象可以分为三个代:

  1. 年轻代(Young Generation):包含了刚刚创建的对象。通常情况下,大部分对象在创建之后很快就会变成垃圾。因此,年轻代中的对象存活时间较短。

  2. 中年代(Intermediate Generation):包含了经过一定时间仍然存活的对象。这些对象可能被多次引用,但仍不具备长期存活的特征。

  3. 老年代(Old Generation):包含了存活时间较长的对象,通常是经过多次垃圾回收仍然存活的对象。这些对象往往是程序中的核心数据结构或全局对象,它们的存活时间相对较长。

分代回收基于一种观察:大部分对象的生命周期都是短暂的,只有少数对象会长时间存活。因此,分代回收将重点放在年轻代上,采用更频繁的、轻量级的垃圾回收策略,如快速的引用计数、标记-清除等。对于存活时间较长的对象,则采用更复杂、耗时较长的回收策略,如标记-整理、分代清理等。

通过这种分代的方式,垃圾回收器可以更加高效地管理内存,减少回收整个堆内存的频率,提高程序的性能和响应速度。

# 查看分代回收的阈值
print(gc.get_threshold())  # 输出:(700, 10, 10)

6. 弱引用


在 Python 中,弱引用(Weak Reference)是一种特殊类型的引用,它不会增加对象的引用计数。换句话说,弱引用不会阻止其引用的对象被垃圾回收器回收。

弱引用通常用于解决循环引用导致的内存泄漏问题,其中两个或多个对象之间互相引用,但又没有被其他地方引用。在这种情况下,即使这些对象已经不再被程序需要,它们仍然无法被垃圾回收,因为它们之间的循环引用导致引用计数不为零。

Python 的 weakref 模块提供了对弱引用的支持。以下是一些常见的用法和函数:

1. weakref.ref(object, callback=None)

  • 创建一个对对象的弱引用,并返回一个弱引用对象。
  • 可以通过 callback 参数指定一个回调函数,在对象被垃圾回收时调用该函数。

2. weakref.proxy(object, callback=None)

  • 创建一个对对象的弱引用代理,并返回一个代理对象。
  • 与 ref() 不同的是,通过代理对象可以像访问原始对象一样访问其属性和方法。

3. weakref.getweakrefs(object)

  • 返回与对象相关联的所有弱引用的列表。

4. weakref.getweakrefcount(object)

  • 返回与对象相关联的弱引用的数量。

5. 弱引用对象的 .weakref 属性

  • 对象被弱引用时,会自动创建一个 .weakref 属性,该属性保存着对弱引用的引用。

示例用法:

import weakrefclass Player:def __init__(self, name):self.name = nameself.friends = weakref.WeakSet()  # 使用弱引用集合保存朋友列表def add_friend(self, friend):self.friends.add(friend)def remove_friend(self, friend):self.friends.discard(friend)def __repr__(self):return f"Player({self.name})"# 创建玩家对象
player1 = Player("Alice")
player2 = Player("Bob")
player3 = Player("Charlie")# 添加朋友关系
player1.add_friend(player2)
player2.add_friend(player1)
player2.add_friend(player3)
player3.add_friend(player2)# 打印玩家及其朋友列表
print(f"{player1} has friends: {[friend.name for friend in player1.friends]}")
print(f"{player2} has friends: {[friend.name for friend in player2.friends]}")
print(f"{player3} has friends: {[friend.name for friend in player3.friends]}")# 删除玩家对象
del player2# 打印剩余玩家及其朋友列表
print(f"After deleting player2:")
print(f"{player1} has friends: {[friend.name for friend in player1.friends]}")
print(f"{player3} has friends: {[friend.name for friend in player3.friends]}")

在这个示例中,Player 类表示游戏中的玩家,每个玩家对象有一个 friends 属性,该属性是一个弱引用集合,用于保存该玩家的朋友列表。通过 add_friend 方法和 remove_friend 方法可以添加和删除朋友关系。

在创建玩家对象后,我们建立了一些朋友关系,并打印了每个玩家对象及其朋友列表。然后,我们删除了一个玩家对象(player2),并再次打印剩余的玩家对象及其朋友列表。由于使用了弱引用集合,即使删除了 player2 对象,其朋友列表中的其他玩家对象仍然可以正常访问,不会因为被删除的对象而出现异常。

使用弱引用能够避免循环引用导致的内存泄漏问题,并提高程序的内存利用效率。但需要注意的是,使用弱引用也可能带来一些额外的复杂性,因此在需要时应慎重使用。 

7. gc 模块


Python的gc(Garbage Collector)模块是用于管理内存回收的工具,它提供了一些函数和方法,用于控制和调整Python的垃圾回收行为。下面是gc模块中常用的函数和方法:

1. gc.enable()

  • 启用垃圾回收机制。默认情况下,Python会自动启用垃圾回收,因此通常不需要手动调用此函数。

2. gc.disable()

  • 禁用垃圾回收机制。在某些情况下,可能需要手动禁用垃圾回收,以提高性能或避免特定问题。

3. gc.collect(generation=2)

  • 手动触发垃圾回收。
  • 可以通过指定generation参数来控制回收的代数,默认值为2,表示回收所有代。

4. gc.get_count()

  • 返回当前每个代的垃圾回收计数。
  • 返回一个包含三个整数的元组,分别表示年轻代、中年代和老年代的回收计数。

5. gc.get_threshold()

  • 返回当前每个代的垃圾回收阈值。
  • 返回一个包含三个整数的元组,分别表示年轻代、中年代和老年代的阈值。

6. gc.set_threshold(threshold0[, threshold1[, threshold2]])

  • 设置每个代的垃圾回收阈值。
  • 可以传入一个包含三个整数的元组,分别设置年轻代、中年代和老年代的阈值。

7. gc.get_objects()

  • 返回一个包含所有当前存在的对象的列表。

8. gc.get_referents(*objs)

  • 返回传入对象所引用的所有对象的列表。

9. gc.get_referrers(*objs)

  • 返回引用传入对象的所有对象的列表。

10. gc.is_tracked(obj)

  • 检查一个对象是否被跟踪(是否在垃圾回收器的内部追踪列表中)。

11. gc.get_stats()

  • 返回一个关于垃圾回收器当前状态的字典。

gc模块提供了一些工具来诊断和调试内存管理问题,但在大多数情况下,Python的垃圾回收器会自动处理内存管理,不需要手动干预。

当涉及到 Python 的垃圾回收机制时,面试官可能会问到一些深入的问题,以下是一些可能被问及的问题:

  1. 什么是 Python 的垃圾回收机制?

    • 解释 Python 中的自动内存管理和垃圾回收机制,包括如何追踪和清理不再使用的对象。
  2. Python 使用的是什么类型的垃圾回收算法?

    • 提及 Python 使用的主要是基于引用计数和分代回收的垃圾回收算法。
  3. 什么是引用计数?它是如何工作的?

    • 说明引用计数是一种跟踪每个对象被引用次数的技术,当引用计数为零时,对象被视为不再被使用,从而可以被垃圾回收。
  4. 引用循环是什么?Python 如何处理引用循环?

    • 描述引用循环是指两个或多个对象之间相互引用,导致它们之间的引用计数永远不会为零。解释 Python 如何通过引入弱引用和分代回收来处理引用循环。
  5. Python 的垃圾回收算法中的分代回收是什么意思?

    • 分代回收是一种优化技术,根据对象的存活时间将内存分为不同的代,并针对不同代使用不同的回收策略,以提高垃圾回收的效率。
  6. 如何手动触发垃圾回收?

    • 提及可以使用 gc.collect() 函数手动触发垃圾回收,但一般情况下不建议手动触发,因为 Python 具有自动的垃圾回收机制。
  7. 垃圾回收对 Python 性能有何影响?

    • 分析垃圾回收对程序性能的影响,包括了解如何减少垃圾回收的频率以提高性能。
  8. 什么是循环垃圾回收(Cycle Garbage Collection)?

    • 描述循环垃圾回收是一种针对引用循环的特殊垃圾回收机制,它通过检测和清理引用循环来解决内存泄漏问题。
  9. 如何优化 Python 中的内存管理和垃圾回收?

    • 讨论一些优化内存管理和垃圾回收的技巧,例如减少循环引用、显式删除不再需要的对象等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/811812.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序(六)定位搜索

一、引言 作者上一章讲了微信小程序的地图实现微信小程序(五)地图-CSDN博客,但是还有一个功能是和地图紧密结合的,那就是位置搜索定位,这里作者讲讲实现和原理,包括城市筛选。 二、定位搜索实现 1、位置搜…

如何选择适用于Mac的文件恢复软件?适用于 Mac 的最佳数据恢复软件清单

有人会说,我们的数字生活正变得几乎和我们的物理生活一样重要。我们在线工作,将记忆保存在数码照片库中,在信使中交流,并保留各种文档的数字扫描。 每个人都知道备份是必不可少的。建议每天至少同步一个数字备份(例如…

Lua语法(六)——面相对象编程

参考链接: 系列链接: Lua语法(一) 系列链接: Lua语法(二)——闭包/日期和时间 系列链接: Lua语法(三)——元表与元方法 系列链接: Lua语法(四)——协程 系列链接: Lua语法(五)——垃圾回收 系列链接: Lua语法(六)——面相对象编程 使用Lua表 进行类的模拟&#xff0…

10个经典Python设计模式解析

大家好!今天咱们来聊聊Python编程中的那些“武林秘籍”——设计模式。它们就像编程界的暗号,让你的代码更加优雅、高效。让我们一起揭开这些模式的神秘面纱,看看它们在实际项目中的神奇作用吧! 1. 工厂模式(Factory P…

Day23_学点儿IDEA_单元测试@Test在新module项目中失效、Jackson核心对象 ObjectMapper识别不到

版本 IntelliJ IDEA 2023.2.4 目录结构 Study(Project) ├──JavaSE(Module) │ └──xxxx └──JavaWeb(Module)└──xxxx问题 1.1 在JavaSE项目中正常可以用的单元测试Test,到了JavaWeb项目中不起作用了 1.2 解决方法 如果是新创建的项目,先…

物联网全栈智能应用实训系统

物联网全栈智能应用实训系统是一款集硬件、软件、网络、数据分析与应用开发于一体的综合性实训平台。它旨在帮助学习者全面掌握物联网技术的各个环节,从硬件设备选型、通信协议理解、软件开发、数据分析到应用部署,都能得到充分的实践锻炼。 一、产品构…

Jenkins+AWS CodeCommit(git)

问题 需要使用Jenkins搭建一套CI流,即通过git代码托管拉取代码,构建自定分支的代码,构建出jar,并进一步构建出docker镜像,并推送到docker私有库中。 准备 AWS云准备 这里假设已经在CodeCommit已经存在私有git代码仓…

Comparablae接口

在日常生经常涉及到排序的的问题,排序问题中又不得不涉及到比较的问题。在排序问题中根据不同的规则对多个对象进行比较,然后根据比较内容的不同对对象进行排序。java中的Comparable就是用来定义排序规则的接口。当要对类中的对象进行排序操作时&#xf…

CentOS7上pt-archiver工具进行数据库表归档——筑梦之路

pt-archiver 是一个用于 MySQL 数据归档和清理的强大工具。它可以将旧数据从原表移动到归档表,同时保持原表的性能不受影响。 前提条件 表有做分区或者有时间字段 在线安装 sudo yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm sud…

View-Consistent 3D Editing with Gaussian Splatting

View-Consistent 3D Editing with Gaussian Splatting 使用高斯溅射进行视图一致的3D编辑 Yuxuan Wang 王宇轩11Xuanyu Yi 易轩宇11Zike Wu 吴子可11Na Zhao 赵娜22Long Chen 龙宸33Hanwang Zhang 张汉旺1144 Abstract 摘要 View-Consistent 3D Editing with Gaussian Sp…

Zookeeper与Kafka消息队列

目录 一、Zookeeper 1、zookeeper简介 2、zookeeper的特点 3、zookeeper的工作模式跟工作机制 3.1 工作模式: 3.2工作机制:​编辑 4、zookeeper应用场景及选举机制 4.1 应用场景: 4.2 选举机制: 4.2.1第一次启动选举机制…

每日Bug汇总--Day05

Bug汇总—Day05 一、项目运行报错 二、项目运行Bug 1、**问题描述:**前端将从后台查询的数据作为参数进行get请求,参数为空 原因分析: 这种写法可能只支全局的参数调用方法的传参响应 代码实现 if (this.jishiName) {this.$http({url…

JAVA集合ArrayList

目录 ArrayList概述 add(element) 用法 add(index, element)用法 remove(element)用法 remove(index)用法 get(index)用法 set(index,element) 练习 test1 定义一个集合,添加字符串,并进行遍历&…

什么是塔式服务器?

塔式服务器是服务器类型中比较常见的一种,通常是垂直和水平盒式形状的服务器,和台式塔式计算机比较相似,塔式服务器可以单独放置在通用的办公环境当中,塔式服务器的机箱机构也比其他的服务器要大,有着足够的内部硬盘和…

解析OceanBase v4.2磁盘数据文件支持按需扩展的功能

前言 若你日常习惯使用MySQL,那当使用过Oceanbase分布式数据库后,也许会对OceanBase的磁盘数据文件样式产生这样的疑问:为何储存数据仅用一个大的block_file文件呢? 简要分析下,OceanBase是通过Linux系统调用falloca…

HarmonyOS实战开发-音视频录制、如何实现音频录制和视频录制功能的应用

介绍 音视频录制应用是基于AVRecorder接口开发的实现音频录制和视频录制功能的应用,音视频录制的主要工作是捕获音频信号,接收视频信号,完成音视频编码并保存到文件中,帮助开发者轻松实现音视频录制功能,包括开始录制…

启动Unity发布的exe并且添加启动参数

启动Unity发布的exe并且添加启动参数 在启动Unity的时候添加一些启动的参数。 代码解释 在启动的时候获取的启动参数如果没有获取到正确的启动参数那么就退出程序,这个代码仅仅在发布到windows之后才会生效,在编辑器下这个代码虽然会获取到参数但是不能…

【YOLOv9改进[损失函数]】使用MPDIou回归损失函数帮助YOLOv9模型更优秀

本文中,第一部分概述了各种回归损失函数,当然也包括了今天的主角MPDIou。第二部分内容为在YOLOv9中使用MPDIou回归损失函数的方法。 1 回归损失函数(Bounding Box Regression Loss) 边界框回归损失计算的方法包括GIoU、DIoU、CI…

微服务下使用sentinel进行服务熔断

首先引入sentinel对应依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>下面是示例service代码,通过openFeign完成服务调用 Service public class …

低频电磁仿真 | 新能源汽车性能提升的利器

永磁同步电机 新能源汽车的心脏 近年来&#xff0c;全球变暖的趋势日益加剧&#xff0c;极端天气事件层出不穷&#xff0c;这些现象都反映出当前气候形势的严峻性。为了应对这一全球性挑战&#xff0c;各国纷纷采取行动&#xff0c;制定了一系列降碳、减碳的措施。中国在2020年…