Cpython3.9源碼解析python中的大小整數(shù)
小整數(shù)
/* interpreter state */ #define _PY_NSMALLPOSINTS 257 #define _PY_NSMALLNEGINTS 5
這是CPython
中定義的兩個常量,它們用于控制解釋器狀態(tài)中的小整數(shù)對象池。在CPython
中,小整數(shù)對象池是一種優(yōu)化機制,用于減少對常用小整數(shù)的內(nèi)存分配和銷毀開銷。
_PY_NSMALLPOSINTS
定義了正小整數(shù)對象池的大小。在這里,其值設(shè)置為257,表示解釋器將為從0到256(包含0和256)的整數(shù)預(yù)分配對象并緩存。這些整數(shù)在很多場景下會被頻繁使用,所以事先創(chuàng)建并緩存它們可以提高性能。
_PY_NSMALLNEGINTS
定義了負小整數(shù)對象池的大小。在這里,其值設(shè)置為5,表示解釋器將為從-1到-5(包含-1和-5)的整數(shù)預(yù)分配對象并緩存。
在Python解釋器啟動時,這些小整數(shù)對象會被創(chuàng)建并放入對象池。當需要這些整數(shù)值時,解釋器會直接從對象池中獲取對應(yīng)的對象,而不是動態(tài)創(chuàng)建新對象。這樣,對于這些小整數(shù)值的操作可以更快地進行,節(jié)省了內(nèi)存分配和銷毀的開銷。
static PyObject * get_small_int(sdigit ival) { assert(IS_SMALL_INT(ival)); PyThreadState *tstate = _PyThreadState_GET(); PyObject *v = (PyObject*)tstate->interp->small_ints[ival + NSMALLNEGINTS]; Py_INCREF(v); return v; } typedef int32_t sdigit; /* signed variant of digit */ #define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)
這是get_small_int
函數(shù)的實現(xiàn),它用于從小整數(shù)對象池中獲取一個指定值的小整數(shù)對象。小整數(shù)對象池包含了一定范圍內(nèi)的整數(shù)對象,主要是為了避免對這些常用的整數(shù)對象進行頻繁的內(nèi)存分配和銷毀。
get_small_int
函數(shù)接受一個sdigit
類型的參數(shù)ival
,表示要獲取的整數(shù)值。在函數(shù)內(nèi)部,首先使用assert(IS_SMALL_INT(ival))
確保傳入的整數(shù)值ival
在小整數(shù)對象池的范圍內(nèi)。
接下來,函數(shù)獲取當前線程狀態(tài)(PyThreadState
)并從其中獲取解釋器狀態(tài)(tstate->interp
)。解釋器狀態(tài)包含了小整數(shù)對象池,即small_ints
數(shù)組。
然后,根據(jù)ival
計算出在small_ints
數(shù)組中的索引(ival + NSMALLNEGINTS
),并將對應(yīng)位置的對象賦值給v
。NSMALLNEGINTS
是一個宏定義,表示負小整數(shù)的個數(shù)。假設(shè)我們有一個整數(shù)值 ival
,我們想要在 small_ints
數(shù)組中查找這個值對應(yīng)的預(yù)分配的小整數(shù)對象。NSMALLNEGINTS
是預(yù)分配的負數(shù)的數(shù)量。在 CPython
中,NSMALLNEGINTS
的值通常為5,表示有5個預(yù)分配的負整數(shù)對象(-1, -2, -3, -4, -5)。
現(xiàn)在,我們將通過計算 ival + NSMALLNEGINTS
來找到 small_ints
數(shù)組中的索引。例如,假設(shè) ival
為3。那么,我們可以計算索引如下:
index = ival + NSMALLNEGINTS index = 3 + 5 index = 8
這意味著 small_ints
數(shù)組中的第8個元素(從0開始計數(shù))是我們要查找的整數(shù)對象。在這個例子中,我們將找到預(yù)分配的小整數(shù)對象3,并將其引用計數(shù)加1,然后返回這個對象。
接下來,通過調(diào)用Py_INCREF(v)
增加v
的引用計數(shù),以防止對象在其引用計數(shù)變?yōu)?時被錯誤地回收。
最后,返回指向小整數(shù)對象的指針v
。
總之,get_small_int
函數(shù)的作用是從小整數(shù)對象池中獲取一個指定值的小整數(shù)對象,并增加其引用計數(shù),然后返回該對象。這樣可以提高對常用小整數(shù)的操作性能。
大整數(shù)
/* 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. */
這是CPython
源碼中關(guān)于長整數(shù)表示的一段注釋。它解釋了PyLongObject
如何表示大整數(shù)的絕對值和符號。讓我們逐行分析這個注釋:
1.首先,注釋指出大整數(shù)的絕對值等于:
SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
ob_digit
表示長整數(shù)的每個“數(shù)字”,SHIFT
是每個“數(shù)字”的位數(shù),通常為30或15。ob_size
表示長整數(shù)的符號和長度,它的絕對值表示長整數(shù)的長度,即“數(shù)字”的個數(shù)。
2.對于負數(shù),ob_size
小于0。對于0,ob_size
等于0。
3.在規(guī)范化的數(shù)中,最高有效位(即最高“數(shù)字”)永遠不會為零。此外,在所有情況下,對于所有有效的i,ob_digit[i]
的取值范圍在0到MASK
之間。MASK
的值通常為(1 << PyLong_SHIFT) - 1
,即2**PyLong_SHIFT - 1
。
4.注釋還提到分配函數(shù)負責分配額外的內(nèi)存,以確保ob_digit[0]
到ob_digit[abs(ob_size)-1]
實際上是可用的。
5.最后,注釋中的“警告”部分提醒開發(fā)者,操縱PyVarObject
子類型的通用代碼需要注意整數(shù)會濫用ob_size
的符號位。這是因為ob_size
的符號位同時表示整數(shù)的長度和符號,而通常情況下ob_size
僅用于表示長度。
額外解釋
ob_digit
是一個表示大整數(shù)中每個 “數(shù)字” 的數(shù)組,它是一個整數(shù)數(shù)組,用于表示長整數(shù)對象(PyLongObject
)中的整數(shù)值。每個 “數(shù)字” 都有一個固定的位數(shù),由 PyLong_SHIFT
定義(通常為 30 或 15)。例如,假設(shè)我們有一個長整數(shù)對象,其值為 12345678901234567890。
在這個例子中,假設(shè) PyLong_SHIFT
為 30,這意味著每個 “數(shù)字” 可以表示 2^30 = 1073741824 個不同的值。為了將這個大整數(shù)表示為 ob_digit
數(shù)組,我們需要將整數(shù)拆分為基于 2^30 的 “數(shù)字”。在這種情況下,我們可以將整數(shù)表示為:
12345678901234567890 = 4 * 2^(30*2) + 726238597 * 2^(30*1) + 1026062870 * 2^(30*0)
所以,ob_digit
數(shù)組將包含以下元素:
ob_digit[0] = 1026062870 ob_digit[1] = 726238597 ob_digit[2] = 4
在實際的 CPython
源碼中,PyLongObject
的定義如下:
typedef struct { PyObject_VAR_HEAD digit ob_digit[1]; } PyLongObject;
在這里,ob_digit
是一個長度為1的數(shù)組,但實際上,它是一個可變長度數(shù)組,根據(jù)所需的 “數(shù)字” 數(shù)量動態(tài)分配。要注意的是,當一個 PyLongObject
被創(chuàng)建時,會根據(jù)整數(shù)值的大小動態(tài)分配適當數(shù)量的空間來存儲 ob_digit
數(shù)組。
總之,ob_digit
是一個整數(shù)數(shù)組,用于表示長整數(shù)對象中的大整數(shù)值。每個數(shù)組元素都是一個 “數(shù)字”,具有固定的位數(shù)。這種表示方法使得 CPython
能夠有效地存儲和處理大整數(shù)。
到此這篇關(guān)于Cpython3.9源碼解析python中的大小整數(shù)的文章就介紹到這了,更多相關(guān)Cpython3.9源碼解析大小整數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Keras搭建Mask?R-CNN實例分割平臺實現(xiàn)源碼
這篇文章主要為大家介紹了Keras搭建Mask?R-CNN實例分割平臺實現(xiàn)源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05pytorch 網(wǎng)絡(luò)參數(shù) weight bias 初始化詳解
這篇文章主要介紹了pytorch 網(wǎng)絡(luò)參數(shù) weight bias 初始化詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06python學(xué)習VSCode使用技巧帶你進入高效開發(fā)模式
VsCode是一款開源的編輯器,擁有強大的功能,。由于擁有各種各樣的插件,這就使得VsCode可以做到的事情更多了。在使用的過程中,也是有很多技巧的,掌握一些技巧對于后期寫代碼也會輕松很多2021-09-09數(shù)據(jù)庫操作入門PyMongo?MongoDB基本用法
這篇文章主要為大家介紹了數(shù)據(jù)庫操作入門PyMongo MongoDB基本用法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11基于Python實現(xiàn)Excel轉(zhuǎn)Markdown表格
Markdown(也簡稱md)作為一種輕量級標記語言,因其易寫易讀,效果美觀大方,不僅被眾多網(wǎng)站使用,也是程序員們做筆記、寫文檔的首選。本文將利用Python實現(xiàn)Excel轉(zhuǎn)Markdown表格,感興趣的可以了解一下2022-04-04Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)從序列中移除重復(fù)項且保持元素間順序不變的方法
這篇文章主要介紹了Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)從序列中移除重復(fù)項且保持元素間順序不變的方法,涉及Python針對列表與字典的元素遍歷、判斷、去重、排序等相關(guān)操作技巧,需要的朋友可以參考下2018-03-03