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