您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Python

Python内存管理机制

时间:2023-06-27 14:36:26  来源:  作者:测试玩家勇哥

什么是垃圾?

当我们的Python/ target=_blank class=infotextkey>Python解释器在执行到定义变量的语法时,会申请内存空间来存放变量的值,而内存的容量是有限的,这就涉及到变量值所占用内存空间的回收问题。那么什么是垃圾呢?简单来说垃圾就是指:当一个对象或者说变量没有用了,这时候它就是垃圾了。

a = 10000 # 开辟内存存储值
a = 30000 # 开辟新内存存储值
# 此时10000没有被引用了,变成垃圾,需要被回收内存。

内存泄漏与内存溢出

上面的代码看到有”垃圾“产生了,如果不处理咋办?举个例子:

  1. 你厕所拉屎不冲水,越拉越多,然后有一天,你又想拉,发现厕所堵了,没地拉屎

  2. 你觉得房间还空旷,继续拉屎,慢慢地你房间满了,你也就被屎山覆盖完蛋了。

上面的结果换句话说就是下面:

内存泄漏:程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光
内存溢出:程序在申请内存时,没有足够的内存空间供其使用,出现 out of memory

数据池和缓存:

  1. 小整数池:Python会自动缓存范围在[-5, 256]内的整数对象,避免频繁创建和销毁对象。当多个变量引用相同的整数对象时,它们指向同一个内存地址的同一个对象。

  2. intern机制:intern机制用于缓存并重复使用一些字符串对象,以减少内存开销和提高性能。当Python解释器遇到字符串字面量时,会先检查该字符串是否存在于intern字符串池中。如果存在,则直接返回对应字符串对象的引用;否则,创建一个新的字符串对象,并将其添加到intern字符串池中,以便后续重复使用。

import sys

# 创建两个相同值的字符串对象
str1 = "hello"
str2 = "hello"

# 检查两个字符串对象的内存地址
print(id(str1),id(str2))

# 使用 intern 机制将字符串添加到 intern 字符串池中
str1 = sys.intern(str1)
str2 = sys.intern(str2)

# 再次检查两个字符串对象的内存地址
print(id(str1),id(str2))
  1. 其他缓存机制:Python还使用了其他一些缓存机制,例如常用的空元组、空字典和空集合会被缓存以减少内存开销。

这些数据池和缓存机制可以在一定程度上优化Python的内存使用,特别是对于频繁使用的对象类型或值。

垃圾回收

Python的垃圾回收机制用于解决循环引用和内存泄漏的问题。当一个对象不再被引用时,其占用的内存应该被回收以供其他对象使用。python采用的是引用计数机制为主,标记-清除和分代收集(隔代回收)两种机制为辅的策略

一、引用计数

Python的引用计数机制是内存管理的基础。当对象被创建时,Python会分配内存地址,并对对象进行初始化。所有对象都会维护在一个双向循环链表中,该链表称为refchAIn。每个对象都保存以下信息:

  • 链表中指向前后对象的指针

  • 对象的类型

  • 对象的值

  • 对象的引用计数

  • 对象的长度(适用于list、dict等可变对象)

引用计数增加的情况包括:对象被创建、对象被其他变量引用、对象作为容器的元素、对象作为参数传递到函数中。
引用计数减少的情况包括:对象的别名被显式销毁、对象的别名被赋值给其他对象、对象从容器中被移除或容器被销毁、引用离开其作用域。

我们可以使用sys模块中的getrefcount()函数来查看对象的引用计数。需要注意的是,getrefcount()函数会在内部临时增加对象的引用计数,所以需要减去函数本身的引用计数才能得到对象的真实引用计数。

import sys

# 引用计数
numbers = [1, 2, 3]
ref_count = sys.getrefcount(numbers) - 1
print(ref_count)  	# 输出 1

# 循环引用:对象互相引用
a = [1, 2]
b = [2, 3]
a.Append(b) 	# 计数2
b.append(a) 	# 计数2
del a  	# 计数1
del b  	# 计数1

# 引用自身
c = [1, 2, 3, 4]
c.append(c)

当一个对象的引用计数为0时,表示没有任何变量引用该对象,可以被回收。但引用计数机制无法解决循环引用的问题。
引用计数的缺点:1. 循环引用 2. 维护引用计数消耗资源

二、标记-清除策略

标记-清除算法:用于解决无法通过引用计数回收的垃圾对象的算法。它的基本思想是从根对象开始,通过标记所有可以访问到的对象,然后清除未标记的对象。清除阶段会释放未被引用的对象占用的内存。
该策略在回收垃圾的时候有两步:

标记阶段
在此阶段,垃圾回收器会从一组根对象开始,例如全局变量、活动的函数调用栈和特殊的内部数据结构。这些根对象是我们确定的起始点。垃圾回收器会递归地遍历这些根对象,并标记所有可以从根对象访问到的对象。它会使用一种标记机制,通常是在对象的内存布局中添加一个额外的标记位来表示对象的状态。初始状态下,所有对象的标记位都是未标记的。通过遍历对象之间的引用关系,从根对象开始,垃圾回收器会标记所有可达的对象。如果一个对象被标记,则意味着它是活动的,即仍然被程序使用。未被标记的对象则被认为是垃圾对象。

清除阶段:
垃圾回收器会扫描整个堆内存,并清除所有未被标记的可达对象。这些未被标记的可达对象被认为是垃圾,因为它们不再被程序使用。

标记-清除是一种周期策略,每隔一段时间进行一次扫描,这种过程会暂停整个应用程序,等待标记-清除结束后才会恢复应用的运行。

分代回收策略

因为标记-清除策略会让程序阻塞,为了提高垃圾回收的效率,在标记-清除的基础上进一步建立分代回收,是一种空间换时间提高回收效率的策略。

Python将内存划分为不同的代(generation),包括年轻代(第0代)、中年代(第1代)和老年代(第2代)。这样划分的目的是根据对象的存活时间来优化垃圾回收的效率。

通常情况下,年轻代的对象存活时间较短,而老年代的对象存活时间较长。因此,Python的分代回收策略认为,存活时间较长的对象越来越不可能是垃圾,所以在回收时应该更少地去检查老年代的对象。

触发分代回收的条件由阈值控制。

import gc

print(gc.get_threshold())  # 默认策略阈值:(700,10,10)
# 阈值设置为(700, 10, 10),表示当分配对象的个数达到700时,
# 进行一次0代回收;经过10次0代回收后,触发一次1代回收;
# 经过10次1代回收后,触发一次2代回收。


gc.set_threshold(500, 5, 5)  # 自己设置回收策略阈值

将对象分为不同的代(Generation),每个代有不同的回收频率。新创建的对象属于第0代(扫描算法),经过一次垃圾回收仍存活的对象会晋升到下一代,而不活跃的对象会被更频繁地回收。

思考

  • 什么时候释放不再使用的对象?
    可以通过显式地将对象设置为None或使用del关键字来解除对象的引用。

  • 如何避免循环引用?
    避免循环引用的方法包括使用弱引用或重新设计数据结构以消除循环引用。

  • 如何减少内存占用?
    对于需要频繁创建和销毁的对象,可以考虑使用缓存, 避免重复创建相同的对象。

    当然,咱们搞垃圾系统的,知道那么多这种干啥呢?用python不就是想着easy嘛?你怎么老想着性能呢?



Tags:Python   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Python 可视化:Plotly 库使用基础
当使用 Plotly 进行数据可视化时,我们可以通过以下示例展示多种绘图方法,每个示例都会有详细的注释和说明。1.创建折线图import plotly.graph_objects as go# 示例1: 创建简单...【详细内容】
2024-04-01  Search: Python  点击:(8)  评论:(0)  加入收藏
Python 办公神器:教你使用 Python 批量制作 PPT
介绍本文将介绍如何使用openpyxl和pptx库来批量制作PPT奖状。本文假设你已经安装了python和这两个库。本文的场景是:一名基层人员,要给一次比赛活动获奖的500名选手制作奖状,并...【详细内容】
2024-03-26  Search: Python  点击:(16)  评论:(0)  加入收藏
Python实现工厂模式、抽象工厂,单例模式
工厂模式是一种常见的设计模式,它可以帮助我们创建对象的过程更加灵活和可扩展。在Python中,我们可以使用函数和类来实现工厂模式。一、Python中实现工厂模式工厂模式是一种常...【详细内容】
2024-03-07  Search: Python  点击:(31)  评论:(0)  加入收藏
不可不学的Python技巧:字典推导式使用全攻略
Python的字典推导式是一种优雅而强大的工具,用于创建字典(dict)。这种方法不仅代码更加简洁,而且执行效率高。无论你是Python新手还是有经验的开发者,掌握字典推导式都将是你技能...【详细内容】
2024-02-22  Search: Python  点击:(32)  评论:(0)  加入收藏
如何进行Python代码的代码重构和优化?
Python是一种高级编程语言,它具有简洁、易于理解和易于维护的特点。然而,代码重构和优化对于保持代码质量和性能至关重要。什么是代码重构?代码重构是指在不改变代码外部行为的...【详细内容】
2024-02-22  Search: Python  点击:(33)  评论:(0)  加入收藏
Python开发者必备的八个PyCharm插件
在编写代码的过程中,括号几乎无处不在,以至于有时我们会拼命辨别哪个闭合括号与哪个开头的括号相匹配。这款插件能帮助解决这个众所周知的问题。前言在PyCharm中浏览插件列表...【详细内容】
2024-01-26  Search: Python  点击:(85)  评论:(0)  加入收藏
Python的Graphlib库,再也不用手敲图结构了
Python中的graphlib库是一个功能强大且易于使用的工具。graphlib提供了许多功能,可以帮助您创建、操作和分析图形对象。本文将介绍graphlib库的主要用法,并提供一些示例代码和...【详细内容】
2024-01-26  Search: Python  点击:(86)  评论:(0)  加入收藏
大语言模型插件功能在携程的Python实践
作者简介成学,携程高级安全研发工程师,关注Python/Golang后端开发、大语言模型等领域。一、背景2023年初,科技圈最火爆的话题莫过于大语言模型了,它是一种全新的聊天机器人模型,...【详细内容】
2024-01-26  Search: Python  点击:(73)  评论:(0)  加入收藏
如何使用Python、Apache Kafka和云平台构建健壮的实时数据管道
译者 | 李睿审校 | 重楼在当今竞争激烈的市场环境中,为了生存和发展,企业必须能够实时收集、处理和响应数据。无论是检测欺诈、个性化用户体验还是监控系统,现在都需要接近即时...【详细内容】
2024-01-26  Search: Python  点击:(46)  评论:(0)  加入收藏
Python分布式爬虫打造搜索引擎
简单分布式爬虫结构主从模式是指由一台主机作为控制节点负责所有运行网络爬虫的主机进行管理,爬虫只需要从控制节点那里接收任务,并把新生成任务提交给控制节点就可以了,在这个...【详细内容】
2024-01-25  Search: Python  点击:(58)  评论:(0)  加入收藏
▌简易百科推荐
Python 可视化:Plotly 库使用基础
当使用 Plotly 进行数据可视化时,我们可以通过以下示例展示多种绘图方法,每个示例都会有详细的注释和说明。1.创建折线图import plotly.graph_objects as go# 示例1: 创建简单...【详细内容】
2024-04-01  Python技术    Tags:Python   点击:(8)  评论:(0)  加入收藏
Python 办公神器:教你使用 Python 批量制作 PPT
介绍本文将介绍如何使用openpyxl和pptx库来批量制作PPT奖状。本文假设你已经安装了python和这两个库。本文的场景是:一名基层人员,要给一次比赛活动获奖的500名选手制作奖状,并...【详细内容】
2024-03-26  Python技术  微信公众号  Tags:Python   点击:(16)  评论:(0)  加入收藏
Python实现工厂模式、抽象工厂,单例模式
工厂模式是一种常见的设计模式,它可以帮助我们创建对象的过程更加灵活和可扩展。在Python中,我们可以使用函数和类来实现工厂模式。一、Python中实现工厂模式工厂模式是一种常...【详细内容】
2024-03-07  Python都知道  微信公众号  Tags:Python   点击:(31)  评论:(0)  加入收藏
不可不学的Python技巧:字典推导式使用全攻略
Python的字典推导式是一种优雅而强大的工具,用于创建字典(dict)。这种方法不仅代码更加简洁,而且执行效率高。无论你是Python新手还是有经验的开发者,掌握字典推导式都将是你技能...【详细内容】
2024-02-22  子午Python  微信公众号  Tags:Python技巧   点击:(32)  评论:(0)  加入收藏
如何进行Python代码的代码重构和优化?
Python是一种高级编程语言,它具有简洁、易于理解和易于维护的特点。然而,代码重构和优化对于保持代码质量和性能至关重要。什么是代码重构?代码重构是指在不改变代码外部行为的...【详细内容】
2024-02-22  编程技术汇    Tags:Python代码   点击:(33)  评论:(0)  加入收藏
Python开发者必备的八个PyCharm插件
在编写代码的过程中,括号几乎无处不在,以至于有时我们会拼命辨别哪个闭合括号与哪个开头的括号相匹配。这款插件能帮助解决这个众所周知的问题。前言在PyCharm中浏览插件列表...【详细内容】
2024-01-26  Python学研大本营  微信公众号  Tags:PyCharm插件   点击:(85)  评论:(0)  加入收藏
Python的Graphlib库,再也不用手敲图结构了
Python中的graphlib库是一个功能强大且易于使用的工具。graphlib提供了许多功能,可以帮助您创建、操作和分析图形对象。本文将介绍graphlib库的主要用法,并提供一些示例代码和...【详细内容】
2024-01-26  科学随想录  微信公众号  Tags:Graphlib库   点击:(86)  评论:(0)  加入收藏
Python分布式爬虫打造搜索引擎
简单分布式爬虫结构主从模式是指由一台主机作为控制节点负责所有运行网络爬虫的主机进行管理,爬虫只需要从控制节点那里接收任务,并把新生成任务提交给控制节点就可以了,在这个...【详细内容】
2024-01-25  大雷家吃饭    Tags:Python   点击:(58)  评论:(0)  加入收藏
使用Python进行数据分析,需要哪些步骤?
Python是一门动态的、面向对象的脚本语言,同时也是一门简约,通俗易懂的编程语言。Python入门简单,代码可读性强,一段好的Python代码,阅读起来像是在读一篇外语文章。Python这种特...【详细内容】
2024-01-15  程序员不二    Tags:Python   点击:(162)  评论:(0)  加入收藏
Python语言的特点及应用场景, 同其它语言对比优势
Python语言作为一种高级编程语言,具有许多独特的特点和优势,这使得它在众多编程语言中脱颖而出。在本文中,我们将探讨Python语言的特点、应用场景以及与其他语言的对比优势。一...【详细内容】
2024-01-09    今日头条  Tags:Python语言   点击:(253)  评论:(0)  加入收藏
站内最新
站内热门
站内头条