深入 Python 整数对象的实现
admin
2023-07-31 00:29:41
0

本文会深入探究 在Python 内部整数对象是如何实现的。

在 Python 内部,一个整数对象是用 PyIntObject 结构来表示的,该整数对象的值属性为 long 型。

1234 typedef struct {    PyObject_HEAD    long ob_ival;} PyIntObject;

为了避免每次要用到整数对象的时候都要分配一个新的内存,Python 预先为一批尚未使用的空闲整数对象分配了一块内存。

下面这个结构就是 Python 用来给整数对象分配内存的,这些整数对象又叫作 PyIntObjects 。该结构初始化完成之后,当 Python 脚本中为新的对象赋值的时候就可以直接使用之前分配好的整数对象了。这个结构叫做“PyIntBlock”,定义如下所示:

12345 struct _intblock {    struct _intblock *next;    PyIntObject objects[N_INTOBJECTS];};typedef struct _intblock PyIntBlock;

Python 在给一批整数对象分配内存块时,这些对象实际上并没有被赋值。我们把这些对象叫做“待用的空闲整数对象”。在 Python 程序中,当一个新的整数值被使用时,这个值就会被赋给下一个可用的整数对象。因为空闲整数对象被赋值的过程中不需要内存分配,所以速度很快。

在同一个块内部的这些整数对象是通过叫做“ob_type”的内部指针从后往前倒序链接在一起的。这里需要注意的是,Python 的源码中存在对内部指针的滥用情况,所以对于指针的名字不用太过纠结。

每一个整数块包含了k个整数对象,k等于 1 KB 的内存块可以容纳的整数对象的数目,在我 64 位电脑上大概是 40 个 PyIntObject 对象。当这个块中所有的整数对象都用完了的时候,就会分配一块新的内存给新的整数对象列表。

已经分配的整数对象内存块是通过一个单向链表来记录的。在Python内部这个列表叫做“block_list”。

在 Python 中使用了一种特殊结构提前为一部分小整数分配了空间,以便快速访问。这是一个包含 262 个指向整数对象的指针的数组(在下文会称之为小整数数组)。这些小整数对象会在(前面提到的)整数对象块进行初始化时被分配,它们的范围是 -5 到 256。许多 Python 程序会频繁使用这一范围内的整数,所以这种预处理的办法非常巧妙。

123 #define NSMALLPOSINTS           257#define NSMALLNEGINTS           5static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

值为 -5 的整数对象在这个小整数数组中偏移量为0,也就是说位于数组的第一个位置,值为 -4 的整数对象偏移量就是 1,以此类推。

试想一下,在 Python 脚本中定义下面一个整数会发生什么?

123 >>> a=1>>> a1

当你执行第一行的时候,就调用了 PyInt_FromLong 函数,函数逻辑如下所示:

123456789 if integer value in range 5,256:    return the integer object pointed by the small integers array at the     offset (value + 5).else:    if no free integer object available:        allocate new block of integer objects     set value of the next free integer object in the current block     of integers.    return integer object

在我们这个例子中,整数 1 由小整数数组中第 1 + 5 = 6 个指针所指。函数返回指向该整数对象的指针,然后变量“a”就会指向这个整数对象。

让我们看一下另外一个例子:

123 >>> a=300>>> a300

300 并没有在小整数数组的范围内,所以就需要把一个空的整数对象赋值为 300。

如果你看过 Python 2.6 源码中的 intobject.c 文件,你就会看到许多处理相加、相乘、转换等运算操作的函数。比如说下面这个比较函数:

1234567 static intint_compare(PyIntObject *v, PyIntObject *w){    register long i = v->ob_ival;    register long j = w->ob_ival;    return (i < j) ? 1 : (i > j) ? 1 : 0;}

整数对象的值储存在对象的 ob_ival 属性中,类型为 long。每个值都存放在一个寄存器中以优化存取过程,所以比较操作是在两个寄存器之间完成的。如果 v 指向的整数对象小于 w 指向的整数对象,返回 -1;反之则返回 1。相等的情况下返回 0。

对 Python 中整数的实现就介绍到这里了。希望你们能喜欢这篇文章并且有所收获。如果你有什么想法就在下方留言吧!

相关内容

热门资讯

500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
python绘图库Matplo... 本文简单介绍了Python绘图库Matplotlib的安装,简介如下: matplotlib是pyt...
Prometheus+Graf... 一,Prometheus概述 1,什么是Prometheus?Prometheus是最初在Sound...