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

时间:2018-04-19 17:24:57

标签: python types size cpython

我正在玩sys的{​​{1}},发现getsizeof()(或False)包含的字节数少于0(或{{ 1}})。那是为什么?

True

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

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 也是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 是32。

那是怎么回事?我假设布尔值sys.getsizeof(999999999)sys.getsizeof(9999999999)分别在内部转换为TrueFalse,但为什么零与其他较低整数的大小不同?

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

1 个答案:

答案 0 :(得分:31)

请记住,Python int值具有任意大小。这有什么作用?

好吧,在CPython中, 1 一个int由一个PyLong_Object表示,它有一个4字节块 2 的数组,每个包含30位 3 这个数字的价值。

  • 0根本没有任何问题。
  • 1 - (1<<30)-1需要1个大块。
  • 1<<30 - (1<<60)-1需要2个块。

等等。

这有点过于简单;有关完整详情,请参阅来源中的longintrepr.h

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

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

<子> 1。在不同的实现中,这可能不是真的。 IIRC,Jython与CPython大致相同,但IronPython使用C#&#34; bignum&#34;实施

<子> 2。为什么30位而不是32位?主要是因为pow**的实现可以更简单,更快,如果它可以假设两个数字中的位数&#34;可以被10整除。

<子> 3。它使用C "struct hack"。从技术上讲,Py_LongObject是28个字节,但没有人分配Py_LongObject;然后将malloc 24,28,32,36等字节转换为Py_LongObject *

<子> 4。事实上,Python int是一个C long,只是为了让事情变得混乱。所以C API充满了像PyInt_FromLong这样的东西,其中long意味着&#34; 32位int&#34;和PyLong_FromSize_t long表示&#34; bignum&#34;。

<子> 5。早期版本的Python 2.x并没有很好地集成intlong,但希望没有人再担心这些了。<​​/ sub>