为什么2⁶³的大小是36字节,而2⁶³-1只有24字节?

Why is the size of 2⁶³ 36 bytes, but 2⁶³-1 is only 24 bytes?

Python 中的一切都是对象。所以 Python 中的 int 大小会比平时大。

>>> sys.getsizeof(int())
24

好的,但为什么 2⁶³2⁶³ - 1 相比需要多 12 个字节而不是一个字节?

>>> sys.getsizeof(2**63)
36
>>> sys.getsizeof(2**62)
24

我知道 2⁶³ 是一个 long 而 2⁶³-1 是一个 int,但为什么相差 12 个字节?

没有更直观,我尝试了一些其他的东西:

>>> a = 2**63
>>> a -= 2**62
>>> sys.getsizeof(a)
36

a 仍然存储为 long,即使它现在可以在 int 中。所以这并不奇怪。但是:

>>> a -= (2**63 - 1)
>>> a = 2**63
>>> a -= (2**63 - 1)
>>> a
1L
>>> sys.getsizeof(a)
28

新尺寸。

>>> a = 2**63
>>> a -= 2**63
>>> a
0L
>>> sys.getsizeof(a)
24

变回24字节,但还是用了long。

我得到的最后一件事:

>>> sys.getsizeof(long())
24

问题:

内存存储在这些场景中如何工作?

子题:

为什么有 12 个字节的间隙来添加我们的直觉告诉我们只是 1 位?

为什么int()long()是24字节,而long(1)已经是28字节而int(2⁶²)

注意:Python 3.X 的工作方式有点不同,但并不更直观。这里我主要关注Python 2.7;我没有测试之前的版本。

虽然我没有在文档中找到它,但这是我的解释。

Python 2 隐含地将int提升为long,当值超过int中可以存储的值时。新类型 (long) 的大小是 long 的默认大小,即 32。从现在开始,变量的大小将由它的值决定,它可以上升和上升下来。

from sys import getsizeof as size
a = 1
n = 32

# going up
for i in range(10):
    if not i:
        print 'a = %100s%13s%4s' % (str(a), type(a), size(a))
    else:
        print 'a = %100s%14s%3s' % (str(a), type(a), size(a))
    a <<= n

# going down
for i in range(11):
    print 'a = %100s%14s%3s' % (str(a), type(a), size(a))
    a >>= n


a =                                                                                                    1 <type 'int'>  24
a =                                                                                           4294967296 <type 'long'> 32
a =                                                                                 18446744073709551616 <type 'long'> 36
a =                                                                        79228162514264337593543950336 <type 'long'> 40
a =                                                              340282366920938463463374607431768211456 <type 'long'> 44
a =                                                    1461501637330902918203684832716283019655932542976 <type 'long'> 48
a =                                           6277101735386680763835789423207666416102355444464034512896 <type 'long'> 52
a =                                 26959946667150639794667015087019630673637144422540572481103610249216 <type 'long'> 56
a =                       115792089237316195423570985008687907853269984665640564039457584007913129639936 <type 'long'> 60
a =              497323236409786642155382248146820840100456150797347717440463976893159497012533375533056 <type 'long'> 64
a =    2135987035920910082395021706169552114602704522356652769947041607822219725780640550022962086936576 <type 'long'> 68
a =              497323236409786642155382248146820840100456150797347717440463976893159497012533375533056 <type 'long'> 64
a =                       115792089237316195423570985008687907853269984665640564039457584007913129639936 <type 'long'> 60
a =                                 26959946667150639794667015087019630673637144422540572481103610249216 <type 'long'> 56
a =                                           6277101735386680763835789423207666416102355444464034512896 <type 'long'> 52
a =                                                    1461501637330902918203684832716283019655932542976 <type 'long'> 48
a =                                                              340282366920938463463374607431768211456 <type 'long'> 44
a =                                                                        79228162514264337593543950336 <type 'long'> 40
a =                                                                                 18446744073709551616 <type 'long'> 36
a =                                                                                           4294967296 <type 'long'> 32
a =                                                                                                    1 <type 'long'> 28

如您所见,类型在第一次变得对于 int 而言太大后仍保持 long,初始大小为 32,但大小随值而变化(可以更高或低于 [或等于,显然] 到 32)

因此,为了回答您的问题,int 的基本大小为 24,long 的基本大小为 28,而 long 也有 space 用于节省大值(开始为 4 个字节 - 因此 long 为 32 个字节,但可以根据值上下移动)

至于您的 sub-question,为新数字创建唯一类型(具有唯一大小)是不可能的,因此 Python 具有 "sub classes" 类型 long , 它处理一系列数字,因此,一旦你超过旧的限制 long 你必须使用更新的,它也占更大的数字,因此,它有几个字节。

why does it get 12 more bytes for 2⁶³ compared too 2⁶³ - 1 and not just one?

LP64 system1, a Python 2 int consists of 正好三个 pointer-sized 件:

  • 类型指针
  • 引用计数
  • 实际值,一个Clong int

总共 24 个字节。另一方面,Pythonlongconsists of:

  • 类型指针
  • 引用计数
  • 位数,一个 pointer-sized 整数
  • 值数字的内联数组,每个包含 30 位值,但以 32 位单元存储(其中一个未使用的位在加法和减法期间用于 efficient carry/borrow

2**63需要64位来存储,所以3个30位的数字就够了。由于每个数字都是 4 个字节宽,所以整个 Python long 将占用 24+3*4 = 36 个字节。

换句话说,不同之处在于 long 必须单独存储数字的大小(8 个额外的字节),而 space-efficient 存储值(12 个字节)略少来存储 2**63) 的数字。包括大小,一个long中的值2**63占20个字节。将其与简单 intany 值占用的 8 个字节进行比较,得出观察到的 12 字节差异。

值得注意的是Python3只有一种整型,叫做int,也就是variable-width,实现方式和Python2一样long.


1 64 位 Windows 的不同之处在于它保留了 32 位 long int,大概是为了与大量使用 charshortlong 作为 8、16 和 32 位值的 "convenient" 别名,恰好在 16 位和 32 位系统上都可以工作。要在 x86-64 Windows 上获得实际的 64 位类型,必须使用 __int64 或(在较新的编译器版本上)long longint64_t。由于 Python 2 在内部依赖于 Python int 在各个地方适合 C long,因此 sys.maxint 仍然是 2**31-1,即使在 64 位 Windows.这个怪癖在Python 3中也得到修复,它没有maxint.

的概念