为什么假值(0)的字节数小于True(1)?

Bra*_*roy 30 python size types cpython

我正在玩sys' getsizeof(),发现False(或0)包含的字节数少于True(或1).这是为什么?

import sys

print("Zero: " + str(sys.getsizeof(0)))
print("One: " + str(sys.getsizeof(1)))
print("False: " + str(sys.getsizeof(False)))
print("True: " + str(sys.getsizeof(True)))

# Prints:
# Zero: 24
# One: 28
# False: 24
# True: 28
Run Code Online (Sandbox Code Playgroud)

实际上,其他数字(也包括一个以上的数字)是28个字节.

for n in range(0, 12):
  print(str(n) + ": " + str(sys.getsizeof(n)))

# Prints:
# 0: 24
# 1: 28
# 2: 28
# 3: 28
# 4: 28
# 5: 28
# 6: 28
# 7: 28
# 8: 28
# 9: 28
# 10: 28
# 11: 28
Run Code Online (Sandbox Code Playgroud)

更多:sys.getsizeof(999999999)也是28个字节!sys.getsizeof(9999999999)然而,是32.

发生什么了?我假设布尔值TrueFalse内部转换为01,但为什么零与其他较低整数的大小不同?

旁注:这是否特定于Python如何表示这些项目,或者这通常是如何在操作系统中显示数字?

aba*_*ert 32

请记住,Python int值具有任意大小.这是如何运作的?

好吧,在CPython中,1一个int由a表示PyLong_Object,它有一个4字节块2的数组,每个块保存30位3的数字.

  • 0 根本不需要任何块.
  • 1- (1<<30)-1需要1块.
  • 1<<30- (1<<60)-1需要2块.

等等.

这有点过于简单; 有关详细信息,请参阅longintrepr.h源代码.


在Python 2中,有两种不同的类型,称为intlong.An int由直接嵌入在头中的C 32位有符号整数4表示,而不是由块数组组成.A long就像Python 3 int.

如果使用0L,1L等等进行相同的测试以明确询问long值,您将获得与Python 3中相同的结果.但是没有L后缀,任何适合32位的文字都会给出一个int,而且只有文字是太大了给你long.5(这意味着它(1<<31)-1是一个int,但是1<<31是一个2块long.)


1.在不同的实现中,这可能不是真的.IIRC,Jython与CPython大致相同,但IronPython使用C#"bignum"实现.

2.为什么30位而不是32位?主要是因为实施pow**可以更简单,更快,如果可以假设,在两个"数字"的位数是整除10.

它使用C "struct hack".从技术上讲,a Py_LongObject是28个字节,但没有人分配过Py_LongObject; 然后他们将malloc 24,28,32,36等字节转换为Py_LongObject *.

事实上,Python int是一个C long,只是为了让事情变得混乱.因此,C API充满了之类的东西PyInt_FromLong,其中long的意思是"32位int"和PyLong_FromSize_t其中long的意思是"BIGNUM".

5. Python的2.X的早期版本并没有整合int,并long作为很好,但希望没有人担心这些了.