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