Skip to content

Python的内存管理

Python 的内存管理和存储机制与 C++ 有很大的不同,它更高级,主要依赖于 Python 解释器和垃圾回收机制来管理内存。

1. 堆和栈

Python 中的栈主要用于管理函数调用和局部变量,而堆用于动态分配对象。

  • :用于管理函数调用的上下文,包括局部变量、参数和返回地址等。
  • :用于存储所有动态分配的对象,包括变量、数据结构(如列表、字典等)。Python 的对象通常是通过 malloc 等底层机制分配在堆上。

2. 对象管理和引用计数

Python 采用引用计数(Reference Counting)来管理内存。每个对象都有一个引用计数,当对象被引用时,计数加一,当引用被删除时,计数减一。

  • 引用计数
  • 每个对象都包含一个引用计数器,记录有多少引用指向该对象。
  • 当引用计数变为零时,对象的内存就会被释放。

例子: python a = [1, 2, 3] # 创建一个列表对象,引用计数为 1 b = a # 引用计数增加到 2 del a # 引用计数减少到 1 del b # 引用计数减少到 0,对象被垃圾回收

3. 垃圾回收

虽然引用计数是主要的内存管理方式,但它无法解决循环引用的问题(即两个或多个对象相互引用,导致引用计数永远不为零)。为了解决这一问题,Python 引入了垃圾回收(Garbage Collection,GC)机制。

  • 标记-清除(Mark-and-Sweep)
  • Python 的垃圾回收器会定期检查对象图,标记活动对象并清除未被引用的对象。

  • 分代收集(Generational Collection)

  • Python 将对象分为不同的代(generations),年轻代对象更频繁地进行垃圾回收,而老年代对象较少进行回收。
  • 这种策略基于“新生对象更可能被快速回收”的假设,能够提高垃圾回收的效率。

4. 内存池(Memory Pool)

Python 使用内存池技术来管理小对象的分配和释放,以提高内存分配的效率。

  • 小对象分配器
  • 小对象(大小小于 256 字节)使用专用的内存池进行分配。这些内存池由 Python 的内存管理器管理,避免了频繁调用系统的内存分配函数。

  • 大对象分配

  • 大对象则直接向操作系统申请内存。

5. PyObject 结构

Python 中的每个对象都是 PyObject 结构的实例。这个结构包含了引用计数和类型信息。

  • PyObject 结构
  • 每个对象都有一个引用计数(ob_refcnt)和一个指向类型对象的指针(ob_type)。

c typedef struct _object { int ob_refcnt; // 引用计数 struct _typeobject *ob_type; // 类型指针 } PyObject;

示例说明

Python 中内存管理的简单示例:

import sys

a = [1, 2, 3]  # 创建一个列表对象
print(sys.getrefcount(a))  # 输出 2,因为 sys.getrefcount 也会创建一个临时引用

b = a  # b 引用了 a
print(sys.getrefcount(a))  # 输出 3

del a  # 删除一个引用
print(sys.getrefcount(b))  # 输出 2

del b  # 删除最后一个引用,对象被垃圾回收