Python的整数是如何实现的
创始人
2024-03-15 23:16:33
0

本文我们来聊一聊Python的整数,我们知道 Python 的整数是不会溢出的,换句话说,它可以计算无穷大的数,只要你的内存足够,它就能计算。

而 C 显然没有这个特征,C 里面能表示的整数范围是有限的。但问题是,Python 底层又是 C 实现的,那么它是怎么做到整数不溢出的呢?既然想知道答案,那么看一下整数在底层是怎么定义的就行了。

整数的底层实现

Python 整数在底层对应的结构体是 PyLongObject,我们看一下具体的定义,这里的源码版本为最新的 3.11。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

// Include/cpython/longintrepr.h

struct _longobject {

    PyObject_VAR_HEAD

    digit ob_digit[1];

};

// Include/pytypedefs.h

typedef struct _longobject PyLongObject;

// 将两者合起来可以看成

typedef struct {

    PyObject_VAR_HEAD

    digit ob_digit[1];

} PyLongObject;

// 如果把这个PyLongObject 更细致的展开一下

typedef struct {

    // 引用计数  

    Py_ssize_t ob_refcnt; 

    // 类型

    struct _typeobject *ob_type; 

    // 维护的元素个数

    Py_ssize_t ob_size;

    // digit 类型的数组,长度为 1 

    digit ob_digit[1]; 

} PyLongObject;

别的先不说,就冲里面的 ob_size 我们就可以思考一番。首先 Python 的整数有大小、但应该没有长度的概念吧,那为什么会有一个 ob_size 呢?

从结构体成员来看,这个 ob_size 指的应该就是数组 ob_digit 的长度,而这个 ob_digit 显然只能是用来维护具体的值了。而数组的长度不同,那么对应的整数占用的内存也不同。

所以答案出来了,整数虽然没有我们生活中的那种长度的概念,但它是个变长对象,因为不同的整数占用的内存可能是不一样的。因此这个 ob_size 指的是底层数组的长度,因为整数对应的值在底层是使用数组来存储的。尽管它没有字符串、列表那种长度的概念,或者说无法对整数使用 len 函数,但它是个变长对象。

那么下面的重点就在这个 ob_digit 数组身上了,我们要从它的身上挖掘信息,看看一个整数是怎么放在这个数组里面的。不过首先我们要搞清楚这个 digit 是什么类型,它的定义同样位于 longintrepr.h 中:

1

2

3

4

5

6

7

8

9

10

11

// PYLONG_BITS_IN_DIGIT是一个宏

// 至于这个宏是做什么的我们先不管

// 总之,如果机器是 64 位的,那么它会被定义为 30

// 机器是 32 位的,则会被定义为 15

#if PYLONG_BITS_IN_DIGIT == 30

typedef uint32_t digit;

// ...

#elif PYLONG_BITS_IN_DIGIT == 15

typedef unsigned short digit;

// ...

#endif

由于现在基本上都是 64 位机器,所以我们只考虑 64 位,显然 PYLONG_BITS_IN_DIGIT 会等于 30。因此 digit 等价于 uint32_t,也就是 unsigned int,所以它是一个无符号 32 位整型。

因此 ob_digit 是一个无符号 32 位整型数组,长度为 1。当然这个数组具体多长则取决于你要存储的整数有多大,不同于 Golang,C 数组的长度不属于类型信息。

虽然定义的时候,声明数组的长度为 1,但你可以把它当成任意长度的数组来用,这是 C 语言中常见的编程技巧。至于长度具体是多少,则取决于你的整数大小。显然整数越大,这个数组就越长,占用的空间也就越大。

搞清楚了 PyLongObject 里面的所有成员,那么下面我们就来分析 ob_digit 是怎么存储整数的,以及 Python 的整数为什么不会溢出。

不过说实话,关于整数不会溢出这个问题,相信很多人已经有答案了。因为底层是使用数组存储的,而数组的长度又没有限制,所以当然不会溢出。

转载自:https://www.weidianyuedu.com

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...