windows 64位機器,python3.7;后面的文章中,沒有特別說明的話,都是在該環境下運行
int 占幾個字節?
C語言中(GCC編譯器),int 占據4個字節,python呢?
我們用python內置的 sys.getsizeof 方法來看看
28個字節! 也就是說 int 是占據 28個字節嗎? 再看看下面的
又多了4個字節!
事實上,上面的 1073741824 = 2**30,我們可以試試
sys.getsizeof(2**30-1)
這是什么原因呢,百撕不得騎姐啊;stackoverflow的這篇文章給出了答案。
https://stackoverflow.com/questions/449560/how-do-i-determine-the-size-of-an-object-in-python
我們直接看 Aaron Hall 給出的答案:
也就是說 int 類型,每2 ** 30增加4個字節。
我們試試
sys.getsizeof(2**60)
沒問題,是這個理兒
那python是怎么做到讓 int 占據的字節大小可變長而不報錯的呢?
具體地,我們看一下python的相關源碼(我的是python3.7.4)
源文件:Include/longintrepr.h
/* Long integer representation.
The absolute value of a number is equal to
SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
Negative numbers are represented with ob_size < 0;
zero is represented by ob_size == 0.
In a normalized number, ob_digit[abs(ob_size)-1] (the most significant
digit) is never zero. Also, in all cases, for all valid i,
0 <= ob_digit[i] <= MASK.
The allocation function takes care of allocating extra memory
so that ob_digit[0] ... ob_digit[abs(ob_size)-1] are actually available.
CAUTION: Generic code manipulating subtypes of PyVarObject has to
aware that ints abuse ob_size's sign bit.
*/
struct _longobject {
PyObject_VAR_HEAD
digit ob_digit[1];
};
PyObject_VAR_HEAD 是所有python對象共有的頭部,這里不分析,需要說明的是 這個頭部對象里面有個 ob_size 指明了可變部分的長度。
重點就是 digit ob_digit[1]
digit 是32位無符號整型(和編譯環境有關),ob_digit是一個動態數組,他存儲了int對象的真實值。真實值為數組的每一個元素 * 2**(SHIFT*i)再相加。這里的SHIFT = 30(64位系統),i 為元素在數組中的索引值。
也因為這個設計,python3.7沒有long類型只有int類型,int實際上就是值無限大(不能超出虛擬內存大小)的long。具體為什么要把int和long合並到一起,這是我們下一問了。