python整型图_python源码研究之整型对象探索
?
1.python的整型對象是PyIntObject對象,這個對象是一個不可變對象,即沒有ob_size這個變量,這個對象在c層面實現,只是在基本的pyobject中添加了long ob_ival對象,結構體大概是這樣的:
typedef struct{
PyObject_HEAD;
long ib_ival
} PyIntObject;
而這個對象對應的類型變量就比較復雜了,很長:
這里面就是int這個類型的一下名稱啊,內存大小,以及操作的信息,操作信息是最多的包括:析構函數,比較操作,獲取HASH值,打印,都在這里了。
2.說到python里面的整型是定長對象,那么是不是很好奇定長是多少呢,經過研究發現是24個字節,那么為什么是24個字節呢,看上面的結構體,int型4個字節,long型8個字節,指針4個字節,加起來4+4+8=16個字節,這里我開始也是不明白,后來突然想到噢,c語言的結構體有內存對其,所以內存直接就是3*8=24個字節,不行可以試試,申請的整型都是24個字節。
3.下面說說整型的創建,Python是調用c api創建的整型,Python的整型分為小整數和大整數,那么這個小大是怎么區分的,是根據編譯源碼python時NSMALLPOSINTS區分的,正常的默認編譯是[-5,256]是小整數,其他的為大整數,之所以這么分是因為小整數頻繁被使用,如果每一個都調用c語言的malloc分配內存,使用完再釋放效率很低,所以python使用的內存緩沖池,初始化的時候,python就已經把小整數的內存申請好了,所以小整數的內存地址是不變的。而大整數不是,是動態的,使用的時候申請,所以就有了一個奇怪的東西(這個東西探尋良久,現在醍醐灌頂):
你初始化一個變量在[-5,257]范圍內時id(這個變量),內存地址都一樣,而初始化[-5,257]以外的數值時,每一次都是變化的,見下圖:
(不會縮小圖~~)上面就是這個意思了 兩個變量都為2 地址一樣,兩個變量都是-10地址不一樣
4.小整數對象就是初始化的都準備好了,在內存申請好了,就像一塊死的東西,你需要的時候直接一個引用指過去就行了,引用加1,地址都是一樣的,不會新申請,所以很快。
5.大整數不一樣了,大整數是存儲在一個PyIntBlock中的,PyIntBlock是一個結構體,如下圖
這個結構體的大小是1000字節,一個整數是12個字(32位的機器)節所以 1000/12 = 82個整型,也就是一個PyIntBlock可以有82個整型。
繼續說,PyIntBlock中的block_list是已經使用了多少內存,已經分配了的內存指針,free_list是沒有分配的剩余的內存指針,開始時這倆都是NULL,因為是一個新的PyIntBlock,注意這里block是每一個PyIntBlock的使用內存的情況,而free_list是所有的剩余內存情況,補一句,這些存儲單元都是單項鏈表。
6.所以綜上就可以知道,當free_list為NULL的時候,就需要新建PyIntBlock,此時調用fill_free_list方法,把空閑的快用單向鏈表鏈接起來給free_list,新建一個int對象時,在free_list拿一塊初始化數值,加入Block_list就行了。
7.這里有個坑,當A,B兩個PyIntBlock,A已經全部使用,B使用一半,A某一個元素釋放了的時候,實際是沒有釋放,二十加入了Free_List,這里導致的就是新申請的int類型永遠不會釋放掉,而是給free_list了,(這里我也不明白。。這不就是內存泄露了,。。。思考中)
8.ok就寫介個多吧,下次繼續。?
1.python的整型對象是PyIntObject對象,這個對象是一個不可變對象,即沒有ob_size這個變量,這個對象在c層面實現,只是在基本的pyobject中添加了long ob_ival對象,結構體大概是這樣的:
typedef struct{
PyObject_HEAD;
long ib_ival
} PyIntObject;
而這個對象對應的類型變量就比較復雜了,很長:
這里面就是int這個類型的一下名稱啊,內存大小,以及操作的信息,操作信息是最多的包括:析構函數,比較操作,獲取HASH值,打印,都在這里了。
2.說到python里面的整型是定長對象,那么是不是很好奇定長是多少呢,經過研究發現是24個字節,那么為什么是24個字節呢,看上面的結構體,int型4個字節,long型8個字節,指針4個字節,加起來4+4+8=16個字節,這里我開始也是不明白,后來突然想到噢,c語言的結構體有內存對其,所以內存直接就是3*8=24個字節,不行可以試試,申請的整型都是24個字節。
3.下面說說整型的創建,Python是調用c api創建的整型,Python的整型分為小整數和大整數,那么這個小大是怎么區分的,是根據編譯源碼python時NSMALLPOSINTS區分的,正常的默認編譯是[-5,256]是小整數,其他的為大整數,之所以這么分是因為小整數頻繁被使用,如果每一個都調用c語言的malloc分配內存,使用完再釋放效率很低,所以python使用的內存緩沖池,初始化的時候,python就已經把小整數的內存申請好了,所以小整數的內存地址是不變的。而大整數不是,是動態的,使用的時候申請,所以就有了一個奇怪的東西(這個東西探尋良久,現在醍醐灌頂):
你初始化一個變量在[-5,257]范圍內時id(這個變量),內存地址都一樣,而初始化[-5,257]以外的數值時,每一次都是變化的,見下圖:
(不會縮小圖~~)上面就是這個意思了 兩個變量都為2 地址一樣,兩個變量都是-10地址不一樣
4.小整數對象就是初始化的都準備好了,在內存申請好了,就像一塊死的東西,你需要的時候直接一個引用指過去就行了,引用加1,地址都是一樣的,不會新申請,所以很快。
5.大整數不一樣了,大整數是存儲在一個PyIntBlock中的,PyIntBlock是一個結構體,如下圖
這個結構體的大小是1000字節,一個整數是12個字(32位的機器)節所以 1000/12 = 82個整型,也就是一個PyIntBlock可以有82個整型。
繼續說,PyIntBlock中的block_list是已經使用了多少內存,已經分配了的內存指針,free_list是沒有分配的剩余的內存指針,開始時這倆都是NULL,因為是一個新的PyIntBlock,注意這里block是每一個PyIntBlock的使用內存的情況,而free_list是所有的剩余內存情況,補一句,這些存儲單元都是單項鏈表。
6.所以綜上就可以知道,當free_list為NULL的時候,就需要新建PyIntBlock,此時調用fill_free_list方法,把空閑的快用單向鏈表鏈接起來給free_list,新建一個int對象時,在free_list拿一塊初始化數值,加入Block_list就行了。
7.這里有個坑,當A,B兩個PyIntBlock,A已經全部使用,B使用一半,A某一個元素釋放了的時候,實際是沒有釋放,二十加入了Free_List,這里導致的就是新申請的int類型永遠不會釋放掉,而是給free_list了,(這里我也不明白。。這不就是內存泄露了,。。。思考中)
8.ok就寫介個多吧,下次繼續。
總結
以上是生活随笔為你收集整理的python整型图_python源码研究之整型对象探索的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python解压打开文件过多_自动解压大
- 下一篇: python查找指定字符串并替换_pyt