Python如何管理int和long类型?

170

有人知道Python是如何在内部处理int和long类型的吗?

  • 它会动态地选择正确的类型吗?
  • int类型的限制是什么?
  • 我正在使用Python 2.6,这与之前的版本不同吗?

我该如何理解下面的代码?

>>> print type(65535)
<type 'int'>
>>> print type(65536*65536)
<type 'long'>

更新:

>>> print type(0x7fffffff)
<type 'int'>
>>> print type(0x80000000)
<type 'long'>

它们不是在CPython中底层动态映射到stdc类型吗? - Aiden Bell
是的,我认为他们是这样做的。我还怀疑所有东西都分配在堆上,所以当一个数字需要更高的精度时,他们只需使用realloc重新分配即可。但我不太确定,所以我会把答案留给其他人。 - zneak
2
您也可以使用 var = 666L 强制 Python 使用长变量。 - qba
10
@Ignacio:错误的,CPython中的整数int是C语言中的long类型(默认为带符号的)...请参见 <CPython 2.X source>/Include/intobject.h:typedef struct { PyObject_HEAD long ob_ival; } PyIntObject;无论如何,在Python 2.x中,int类型允许负数;C语言中的unsigned类型无法处理负数。 - John Machin
PEP 237讨论了Python在底层是如何使所有这些看起来毫不费力的。 - Carel
9个回答

169

intlong几个版本之前被"统一"。在此之前,通过数学运算可能会导致int溢出。

3.x进一步发展,完全消除了long,只有int

  • Python 2sys.maxint包含Python int可容纳的最大值。
    • 在64位Python 2.7上,大小为24字节。使用sys.getsizeof()进行检查。
  • Python 3sys.maxsize包含Python int可以是的最大字节数。
    • 这将是32位中的千兆字节,64位中的 exabytes。
    • 这样一个大的int将具有类似于8的幂次方sys.maxsize的值。

38
Python3把这种类型称为'int',尽管它的行为更像2.x中的'long'。 - Roger Pate
3
Ted评论:如下所述,请注意将大于maxint的内容强制转换为int仍将导致long类型。
type(int(sys.maxint+1)) <type 'long'>
- StuartLC
5
在Python3中,它是sys.maxsize。 - pylover
4
sys.maxsize与整数无关。Python 3的sys.maxint已被移除,因为整数没有最大限制(Python 3的int与Python 2的long相同)。 - asmeurer
2
我有点困惑。在我的64位Windows系统上,sys.maxint的值为2^31 -1。 - Christofer Ohlsson
显示剩余6条评论

25

这个PEP应该会有所帮助。

最重要的是,在Python版本大于2.4的情况下,你真的不需要担心它。


23
如果你需要在C语言中使用long这种数据类型,并调用一个int函数,那么你就必须要担心它是否能够适应int类型(即长整型能否转换为整型)。即使进行强制类型转换也无济于事。我最近就遇到了这样的问题。 - Macke
2
@Macke:这个评论救了我,我以为int会奏效,一直想知道为什么还是会出现Jython异常。 - ted
1
@Macke 绝对正确。在我目前工作的公司中,我们有一个用Python编写的模拟器,通过Tkinter条目接收用户输入,并通过TCP/IP将转换后的值发送到一个模拟嵌入式系统的客户端(用C/C++编写)。想象一下当您在基于Python的条目中插入100000000000000000000000时会发生什么... :P - rbaleksandar

14

在Python 2中,类型将根据值的大小自动设置。下面可以找到最大值的指南。

默认Int在Python 2中的最大值为65535,超过这个值将是一个长整型。

例如:

>> print type(65535)
<type 'int'>
>>> print type(65536*65536)
<type 'long'>
在Python 3中,long数据类型已被移除,所有整数值都由Int类处理。 Int的默认大小取决于您的CPU架构。
例如:
- 在32位系统中,默认整数类型为'Int32' - 在64位系统中,默认整数类型为'Int64'
每种类型的最小/最大值如下:
- Int8:[-128,127] - Int16:[-32768,32767] - Int32:[-2147483648,2147483647] - Int64:[-9223372036854775808,9223372036854775807] - Int128:[-170141183460469231731687303715884105728,170141183460469231731687303715884105727] - UInt8:[0,255] - UInt16:[0,65535] - UInt32:[0,4294967295] - UInt64:[0,18446744073709551615] - UInt128:[0,340282366920938463463374607431768211455]
如果Int的大小超过上述限制,Python将自动更改其类型并分配更多内存以处理此增加的最小/最大值。在Python 2中,它会转换为“长”(long),但现在只会转换为下一个Int大小。
例如:如果您正在使用32位操作系统,则默认情况下Int的最大值为2147483647。如果分配了2147483648或更多的值,则类型将更改为Int64。
有不同的方法来检查int的大小和内存分配。
注意:在Python 3中,使用内置的type()方法将始终返回,无论您使用什么大小的Int。

这是最详细的答案,但我不确定它对于Python 3来说是否足够详细(而Python 2的信息可以直接删除)。那么任意长度的长整型呢?使用C风格的类型直接编写代码,例如移植C代码或进行低级编程怎么办? - Aleksandr Dubinsky
Python 2中默认int的最大值在我的典型64位安装中不是65535(而且Python 2的行为仍然对我们中的一些人很有兴趣): mad@shuttle:~$ python --version; python -c 'print(type(0x7FFFffffFFFFffff))' Python 2.7.16 <type 'int'> mad@shuttle:~$ - Martin Dorey
如果Int64是默认值,那么Int8/Int16/Int32将永远不会被使用,因为Int64已经比它们大了,当内部使用Int8/Int16/Int32时呢? - harry

6

在我的机器上:

>>> print type(1<<30)
<type 'int'>
>>> print type(1<<31)
<type 'long'>
>>> print type(0x7FFFFFFF)
<type 'int'>
>>> print type(0x7FFFFFFF+1)
<type 'long'>

Python使用int(32位有符号整数,我不知道它们在底层是否为C ints)来表示适合32位的值,但对于超出此范围的任何值,自动切换到longs(任意大的位数 - 即bignums)。我猜这样可以加快小值的运算速度,并避免任何溢出,并且转换到bignums是无缝的。

4

有趣。在我的64位(i7 Ubuntu)机器上:

>>> print type(0x7FFFFFFF)
<type 'int'>
>>> print type(0x7FFFFFFF+1)
<type 'int'>

如果在更大的机器上,将会使用64位整数。


2
Python使用机器可用的更大整数类型。 因此,在32位机器上,int将具有32位大小,而在64位机器上,它将具有64位大小。 但是,可能存在定义64位整数的32位架构,在这种情况下,Python将使用64位整数。 - Bakuriu

4

Python 2.7.9自动提升数字。对于不确定是使用int()还是long()的情况。

>>> a = int("123")
>>> type(a)
<type 'int'>
>>> a = int("111111111111111111111111111111111111111111111111111")
>>> type(a)
<type 'long'>

2

从Python 3.x开始,统一的整数库比旧版本更加智能。在我的(i7 Ubuntu)计算机上,我得到了以下结果:

>>> type(math.factorial(30))
<class 'int'>

有关实现细节,请参考Include/longintrepr.h, Objects/longobject.c和Modules/mathmodule.c文件。最后一个文件是动态模块(编译为so文件)。代码有良好的注释,易于理解。


1
它管理它们,因为intlong是兄弟类定义。它们具有适当的方法来执行+、-、*、/等操作,这些操作将产生适当类的结果。
例如:
>>> a=1<<30
>>> type(a)
<type 'int'>
>>> b=a*2
>>> type(b)
<type 'long'>

在这种情况下,类int具有一个__mul__方法(实现*),当需要时创建一个long结果。

0

继续回答这里提出的所有答案,特别是 @James Lanes 提供的

整数类型的大小可以用以下公式表示:

总范围 = (2 ^ 位制) 下限 = -(2 ^ 位制)*0.5 上限 = ((2 ^ 位制)*0.5) - 1


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接