- 实验结果
本机环境64位Python 3.12
- 内存布局图
0 4 8 12 16 20 24 28
|----------|----------|----------|----------|----------|----------|----------|
| ob_refcnt | ob_type | ob_digit | pad |
|----------|----------|----------|----------|----------|----------|----------|
在这个布局图中,各个部分的含义如下:
- 1) ob_refcnt:4 字节,用于存储对象的引用计数。
- 2) ob_type:4 字节,指向对象的类型信息。
- 3) ob_digit :8字节,存储整数值。
- 4) pad: 12字节,用于填充和对齐,保证整个结构体大小为 28 字节。
在这个布局中,整数值被存储在 ob_digit
中,而引用计数和类型信息分别存储在 ob_refcnt
和 ob_type
中。填充字节用于对齐和填充,保证整个结构体的大小为 28 字节。这种布局使得整数对象在 Python 3.7 版本之后能够更加高效地存储整数值,并且减少了内存占用。
- 数据结构
在 Python 中,整数类型的结构体在 CPython 中被定义为 _PyLongObject
,其中存储了整数对象的相关信息。以下是整数类型结构体 _PyLongObject
的简化版本:
typedef struct {
PyObject_VAR_HEAD
// other fields specific to long integers
digit ob_digit[1];
} PyLongObject;
在这个结构体中,PyObject_VAR_HEAD
包含了对象的引用计数和类型信息,ob_digit
是一个数组,用于存储整数值。实际上,ob_digit
是一个灵活数组,其大小可以根据需要进行调整,以便存储长整型数据。
在 Python 3.7 版本之后,整数对象的内存布局调整,PyLongObject
结构体中的 ob_digit
数组用于存储整数值,而不再需要额外的字段来存储整数值。这样的设计使得整数对象的内存占用更加高效,同时也提高了整数对象的操作效率。
- 再往下一层
PyObject_VAR_HEAD
是 Python 中用于定义可变大小对象的结构体宏。在 CPython 中,所有可变大小的对象(如列表、元组、字符串等)都以相同的结构开始,其中包含对象的引用计数和类型信息。
在 Python 3.7 中,PyObject_VAR_HEAD
的定义如下:
#define PyObject_VAR_HEAD \
PyObject_HEAD \
Py_ssize_t ob_size; /* Number of items in variable part */
其中:
- PyObject_HEAD 包含了对象的引用计数和类型信息,通常定义为
#define PyObject_HEAD \
_PyObject_HEAD_EXTRA \
Py_ssize_t ob_refcnt; \
struct _typeobject *ob_type;
- ob_size 表示可变部分中的项目数量,例如,对于列表对象,ob_size 表示列表中元素的个数。
因此,PyObject_VAR_HEAD 宏实际上是将 PyObject_HEAD 中的引用计数和类型信息与 ob_size 合并在一起,用于定义可变大小对象的结构体。这样的设计使得 Python 能够灵活地处理可变大小对象,同时保持了一致的对象表示方式。
PyObject
是 Python 中所有对象的基本结构体,定义了所有 Python 对象共享的通用属性。在 CPython 中,PyObject
结构体的定义如下:
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
其中:
- _PyObject_HEAD_EXTRA 包含了一些额外的信息,通常用于调试和特定配置的目的。
- ob_refcnt 表示对象的引用计数,用于跟踪对象的引用情况,当引用计数为 0 时,对象会被销毁。
- ob_type 指向对象的类型对象,用于标识对象的类型信息,如整数、字符串、列表等。
PyObject 结构体是所有 Python 对象的基础,所有的 Python 对象都是以 PyObject 结构体为基础进行扩展的。通过这种方式,Python 实现了对象的通用性和灵活性,使得不同类型的对象可以共享相同的基本属性和行为。