在不同的Python对象上试验魔术方法(特别是__sizeof__)我偶然发现了以下行为:
Python 2.7
>>> False.__sizeof__()
24
>>> True.__sizeof__()
24
Python 3.x
>>> False.__sizeof__()
24
>>> True.__sizeof__()
28
在Python 3中改变了什么使True的大小大于False的大小?
这是因为bool是Python 2和3中int的子类。
>>> issubclass(bool, int)
True
但是int实现已经改变了。 在Python 2中,int是32位或64位的,取决于系统,而不是任意长度的长度。 在Python 3中,int是任意长度的 - Python 2的长度被重命名为int并且原始的Python 2 int完全被删除。
在Python 2中,您可以获得长对象1L和0L完全相同的行为:
Python 2.7.15rc1 (default, Apr 15 2018, 21:51:34)
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.getsizeof(1L)
28
>>> sys.getsizeof(0L)
24
long / Python 3 int是一个可变长度的对象,就像一个元组 - 当它被分配时,分配了足够的内存来保存表示它所需的所有二进制数字。 可变部分的长度存储在对象头中。 0不需要二进制数字(其可变长度为0),但即使1溢出,也需要额外的数字。
0表示为长度为0的二进制字符串:
<>
1表示为30位二进制字符串:
<000000000000000000000000000001>
Python中的默认配置在uint32_t中使用30位; 所以2 ** 30 - 1仍然适合x86-64的28字节,而2 ** 30则需要32;
2 ** 30 - 1将显示为:
<111111111111111111111111111111>
所有30个值位设置为1; 2 ** 30将需要更多,它将具有内部表示:
<000000000000000000000000000001000000000000000000000000000000>
至于True使用28个字节而不是24个 - 你不必担心。 True是一个单例,因此在任何Python程序中总共只丢失4个字节,而对于每次使用True都不会丢失4个字节。