我正在玩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)
分别在内部转换为True
和False
,但为什么零与其他较低整数的大小不同?
附注:这是否特定于Python如何表示这些项目,或者这通常是如何在操作系统中显示数字?
答案 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中,有两种不同的类型,称为int
和long
。 int
由直接嵌入标头中的C 32位有符号整数 4 表示,而不是由数组块组成。 long
就像Python 3 int
。
如果您使用0L
,1L
等进行相同的测试,以明确询问long
值,您将获得与Python 3相同的结果。但没有L
后缀,任何符合32位的文字都会给你一个int
,只有太大的文字才会给你long
s。 5 (这意味着(1<<31)-1
是int
,但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并没有很好地集成int
和long
,但希望没有人再担心这些了。</ sub>