为什么 False 值 (0) 的字节数小于 True (1)?
Why is a False value (0) smaller in bytes than True (1)?
我正在研究 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
事实上,其他数字(也有一些数字不止一个)都是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
更进一步:sys.getsizeof(999999999)
也是28个字节!然而,sys.getsizeof(9999999999)
是 32。
所以这是怎么回事?我假设布尔值 True
和 False
在内部分别转换为 0
和 1
,但为什么零与其他较低整数的大小不同?
附带问题:这是否特定于 Python (3) 表示这些项目的方式,或者这通常是 OS 中数字的呈现方式?
请记住 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
。
在Python2中,有两个独立的类型,分别叫做int
和long
。 int
由直接嵌入 header 中的 C 32 位带符号整数 4 表示,而不是块数组。一个 long
就像一个 Python 3 int
.
如果您对 0L
、1L
等进行相同的测试,明确要求 long
值,您将得到与 [=105= 相同的结果] 3. 但是没有 L
后缀,任何适合 32 位的文字都会给你一个 int
,只有太大的文字会给你 long
s. 5(这意味着 (1<<31)-1
是一个 int
,但 1<<31
是一个 2-chunk long
。)
1.在不同的实现中,这可能不是真的。 IIRC,Jython 做的事情与 CPython 大致相同,但 IronPython 使用 C# "bignum" 实现。
2。为什么是 30 位而不是 32 位?主要是因为pow
和**
的实现如果能假设两个"digits"的位数能被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
表示“32 位整数”,而 PyLong_FromSize_t
其中 long
表示 "bignum".
5. Python 2.x 的早期版本没有很好地集成 int
和 long
,但希望没有人再担心这些了。
我正在研究 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
事实上,其他数字(也有一些数字不止一个)都是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
更进一步:sys.getsizeof(999999999)
也是28个字节!然而,sys.getsizeof(9999999999)
是 32。
所以这是怎么回事?我假设布尔值 True
和 False
在内部分别转换为 0
和 1
,但为什么零与其他较低整数的大小不同?
附带问题:这是否特定于 Python (3) 表示这些项目的方式,或者这通常是 OS 中数字的呈现方式?
请记住 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
。
在Python2中,有两个独立的类型,分别叫做int
和long
。 int
由直接嵌入 header 中的 C 32 位带符号整数 4 表示,而不是块数组。一个 long
就像一个 Python 3 int
.
如果您对 0L
、1L
等进行相同的测试,明确要求 long
值,您将得到与 [=105= 相同的结果] 3. 但是没有 L
后缀,任何适合 32 位的文字都会给你一个 int
,只有太大的文字会给你 long
s. 5(这意味着 (1<<31)-1
是一个 int
,但 1<<31
是一个 2-chunk long
。)
1.在不同的实现中,这可能不是真的。 IIRC,Jython 做的事情与 CPython 大致相同,但 IronPython 使用 C# "bignum" 实现。
2。为什么是 30 位而不是 32 位?主要是因为pow
和**
的实现如果能假设两个"digits"的位数能被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
表示“32 位整数”,而 PyLong_FromSize_t
其中 long
表示 "bignum".
5. Python 2.x 的早期版本没有很好地集成 int
和 long
,但希望没有人再担心这些了。