ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python 中的内存管理

2023-07-19 13:05:52  阅读:250  来源: 互联网

标签:Python 内存 堆栈


当涉及到用于管理内存的主要方法时,有两种主要方法可以处理两种不同的用例:

  1. 引用计数
  2. 使用标记和扫描进行循环检测

在进一步了解这些方法之前,了解有两种类型的内存位置 — 堆栈是很有用的。

这里的堆不是我们通常知道的堆数据结构,而是一种执行内存管理操作的内存管理结构,例如内存的分配和释放,主要由 Python 运行时管理。

至于存储在哪里,重要的是要注意,本地范围内的所有函数调用和变量都存储在堆栈中,而包括类和数据结构在内的任何对象都存储在堆中。作为一般的经验法则,如果可以事先预测数据的确切大小 - 在大多数情况下,它将存储在堆栈中。但是,它可能因具体情况而异。

引用计数

创建变量时,该变量的引用存储在内存中,就像在其他语言中一样。您可以使用该函数检查对象的内存位置。这些引用通过维护这些引用的计数来维护在内存中。id

>>> a = 'crunchcode'>>>  id(a)140654166163184>>>
 hex(id(a)
)
'0x7fec999c3ef0'

有很多方法可以获取引用计数,但是,我喜欢使用该模块,因为它的简洁性。ctypes

>>> import ctypes
>>> ctypes.c_long.from_address(id(a)).value
1

这显示了我们存储在内存中的指向对象的引用数量。crunchcode

让我们看看当我将新变量分配给(现有变量)时会发生什么。ba

>>> import ctypes
>>> a = [79]
>>> ctypes.c_long.from_address(id(a)).value 1
>>> b = a>>> ctypes.c_long.from_address  (id(a
)).value 2

正如您现在可能注意到的那样,我们的参考计数增加了 1。这是因为两个变量都引用相同的内存地址。ab

为了更好地理解这一点,我们需要了解副本和副本之间的另一个概念差异。shallowdeep

通常,当我们在 Python 中将一个变量分配给另一个变量时,如上例所示,python 将其引用存储到相同的内存位置,并将引用计数增加 1。这称为副本。shallow

这也可能会在代码中产生意想不到的效果:

>>> a = [1, 2]>>> b = a>>> a[1, 2]>>> b[1, 2]>>> a

[1]


 = 100    >>> b

[1, 100
]

但是,对于字符串,不会观察到相同的行为:

>>> a = 'crunchcode'>>> b = a>>> a
 = 'aa'>>> b'crunchcode' 


刚刚到底发生了什么?字符串是不可变的。每次更改值时都会创建一个新字符串,即使内容相同也是如此。这是一个完全不同的主题,超出了本文的范围,我打算在未来介绍。

现在让我们谈谈deepcopy

>>>  import copy>>> import ctypes
>>> a = [1, 2]>>> b = copy.deepcopy
(a)>>> id(a)140478929984320
>>> id(b)


140478929986816
     >>>  a[1] =
100
>>> b
[1, 2]>>> a[1, 100]
py
>>> ctypes.c_long.from_address(id(a
)).value 2
>>> ctypes.c_long.from_address(id(b)).value
1 

当我们使用 时,Python 运行时不会将变量指向相同的内存地址,相反,它实际上复制内存地址中存在的值并分配一个新的内存位置,如上面的不同结果所证明的那样。因此,每个变量的引用计数也会单独存储。deepcopyid

一旦运行时检测到特定对象的引用计数为 0,就会释放内存空间。

周期检测

Python 还在其垃圾回收器中实现了一种名为 Mark and Sweep 的算法,以释放具有循环引用的内存。

该算法的解释超出了本文的范围,但是,如果您愿意,可以在Mark-and-Sweep:垃圾收集算法 - GeeksforGeeks上了解更多信息。

但是,当执行标记和扫描算法时,现在释放了被占用的内存的微小片段。如果多次执行此操作,则会导致称为碎片的问题,其中连续的内存块不再是真正连续的,从而导致空间量越来越少,最终导致内存异常。可以运行碎片整理算法来解决此问题,但是,这会导致额外的开销。

标签:Python,内存,堆栈
来源:

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有