




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第Python對(duì)象的底層實(shí)現(xiàn)源碼學(xué)習(xí)目錄1.PyObject:對(duì)象的基石2.PyVarObject:變長(zhǎng)對(duì)象的基礎(chǔ)2.1浮點(diǎn)對(duì)象2.2列表對(duì)象3.PyTypeObject:類(lèi)型的基石4.PyType_Type:類(lèi)型的類(lèi)型5.PyBaseObject_Type:類(lèi)型之基6.補(bǔ)充在Python源碼學(xué)習(xí)筆記:Python萬(wàn)物皆對(duì)象中,我們對(duì)Python的對(duì)象類(lèi)型體系有了一定的認(rèn)識(shí),這篇博客將從源碼層面來(lái)介紹Python中萬(wàn)物皆對(duì)象的底層實(shí)現(xiàn)。
1.PyObject:對(duì)象的基石
在Python解釋器的C層面,一切對(duì)象都是以PyObject為基礎(chǔ)的
C源碼如下:
typedefstruct_object{
_PyObject_HEAD_EXTRA
Py_ssize_tob_refcnt;
PyTypeObject*ob_type;
}PyObject;
源碼解讀:
_PyObject_HEAD_EXTRA:主要用于實(shí)現(xiàn)雙向鏈表(分析源碼時(shí)暫時(shí)忽略)
ob_refcnt:引用計(jì)數(shù),用于垃圾回收機(jī)制,當(dāng)這個(gè)參數(shù)減少為0時(shí)即代表對(duì)象要被刪除了(Py_ssize_t當(dāng)作int或long即可,感興趣的話(huà)可以去看下它的定義)
ob_type:類(lèi)型指針,指向?qū)ο蟮念?lèi)型對(duì)象(PyTypeObject,稍后介紹),類(lèi)型對(duì)象描述實(shí)例對(duì)象的數(shù)據(jù)及行為。如PyLongObject的ob_type指向的就是PyLong_Type
2.PyVarObject:變長(zhǎng)對(duì)象的基礎(chǔ)
PyVarObject與PyObject相比只多了一個(gè)屬性ob_size,它指明了邊長(zhǎng)對(duì)象中有多少個(gè)元素
C源碼如下:
typedefstruct{
PyObjectob_base;
Py_ssize_tob_size;/*Numberofitemsinvariablepart*/
}PyVarObject;
定長(zhǎng)對(duì)象和變長(zhǎng)對(duì)象的大致結(jié)構(gòu)圖示如下:
宏定義:對(duì)于具體對(duì)象,視其大小是否固定,需要包含頭部PyObject或PyVarObject,為此,頭文件準(zhǔn)備了兩個(gè)宏定義,方便其他對(duì)象使用:
#definePyObject_HEADPyObjectob_base;
#definePyObject_VAR_HEADPyVarObjectob_base;
2.1浮點(diǎn)對(duì)象
這里簡(jiǎn)單的以浮點(diǎn)對(duì)象作為定長(zhǎng)對(duì)象的例子,介紹一下相關(guān)概念,后續(xù)會(huì)詳細(xì)分析float對(duì)象的源碼。
對(duì)于大小固定的浮點(diǎn)對(duì)象,需要在PyObject頭部的基礎(chǔ)上,用一個(gè)雙精度浮點(diǎn)數(shù)double加以實(shí)現(xiàn):
typedefstruct{
PyObject_HEAD
doubleob_fval;
}PyFloatObject;
圖示如下:
2.2列表對(duì)象
這里簡(jiǎn)單的以列表對(duì)象作為變長(zhǎng)對(duì)象的例子,介紹一下相關(guān)概念,后續(xù)會(huì)詳細(xì)分析list對(duì)象的源碼。
對(duì)于大小不固定的列表對(duì)象,需要在PyVarObject頭部的基礎(chǔ)上,用一個(gè)動(dòng)態(tài)數(shù)組加以實(shí)現(xiàn),數(shù)組存儲(chǔ)了列表包含的對(duì)象的指針,即PyObject指針:
typedefstruct{
PyObject_VAR_HEAD
PyObject**ob_item;
Py_ssize_tallocated;
}PyListObject;
源碼解讀:
ob_item:指向動(dòng)態(tài)數(shù)組的指針,數(shù)組中保存元素對(duì)象指針
allocated:動(dòng)態(tài)數(shù)組的總長(zhǎng)度,即列表當(dāng)前的容量
ob_size:當(dāng)前元素個(gè)數(shù),即列表當(dāng)前的長(zhǎng)度(這里的長(zhǎng)度是指:列表包含n個(gè)元素,則長(zhǎng)度為n)
圖示如下:
3.PyTypeObject:類(lèi)型的基石
問(wèn)題:不同類(lèi)型的對(duì)象所需存儲(chǔ)空間不同,創(chuàng)建對(duì)象時(shí)從哪得知存儲(chǔ)信息呢?以及如何判斷一個(gè)給定對(duì)象支持哪些操作呢?
注意到,PyObject結(jié)構(gòu)體中包含一個(gè)指針ob_type,指向的就是類(lèi)型對(duì)象,其中就包含了上述問(wèn)題所需要的信息
C源碼如下:(只列出了部分,后續(xù)會(huì)結(jié)合具體類(lèi)型進(jìn)行分析)
typedefstruct_typeobject{
PyObject_VAR_HEAD
constchar*tp_name;/*Forprinting,informat"module.name"*/
Py_ssize_ttp_basicsize,tp_itemsize;/*Forallocation*/
/*Methodstoimplementstandardoperations*/
destructortp_dealloc;
printfunctp_print
getattrfunctp_getattr;
setattrfunctp_setattr;
//...
/*Attributedescriptorandsubclassingstuff*/
PyObject*tp_bases;
//...
}PyTypeObject;
源碼解讀:
PyObject_VAR_HEAD表示PyTypeObject是變長(zhǎng)對(duì)象
tp_name:類(lèi)型名稱(chēng)
tp_basicsize、tp_itemsize:創(chuàng)建實(shí)例對(duì)象時(shí)所需的內(nèi)存信息
tp_print、tp_getattr等:表示該類(lèi)型支持的相關(guān)操作信息
tp_bases:指向基類(lèi)對(duì)象,表示類(lèi)型的繼承信息
PyTypeObject就是類(lèi)型對(duì)象在C層面的表示形式,對(duì)應(yīng)面向?qū)ο笾蓄?lèi)的概念,其中保存著對(duì)象的元信息(即一類(lèi)對(duì)象的操作、數(shù)據(jù)等)。
下面以浮點(diǎn)類(lèi)型為例,列出了PyFloatObject和PyTypeObject之間的關(guān)系結(jié)構(gòu)圖示:(其中兩個(gè)浮點(diǎn)實(shí)例對(duì)象都是PyFloatObject結(jié)構(gòu)體,浮點(diǎn)類(lèi)型對(duì)象float是一個(gè)PyTypeObject結(jié)構(gòu)體變量)
由于浮點(diǎn)類(lèi)型對(duì)象唯一,在C語(yǔ)言層面作為一個(gè)全局變量靜態(tài)定義即可。C源碼如下:(只列出了部分)
PyTypeObjectPyFloat_Type={
PyVarObject_HEAD_INIT(PyType_Type,0)
"float",
sizeof(PyFloatObject),
(destructor)float_dealloc,/*tp_dealloc*/
//...
(reprfunc)float_repr,/*tp_repr*/
//...
源碼解讀:
第二行PyVarObject_HEAD_INIT(PyType_Type,0):初始化了ob_refcnt、ob_type、ob_sie三個(gè)字段,其中ob_type指向了PyType_Type(稍后會(huì)繼續(xù)介紹,它就是type),即:float的類(lèi)型是type
第三行float:將tp_name字段初始化為類(lèi)型名稱(chēng)float
4.PyType_Type:類(lèi)型的類(lèi)型
通過(guò)PyFloat_Type的ob_type字段,我們找到了type所對(duì)應(yīng)的C語(yǔ)言層面結(jié)構(gòu)體變量:PyType_Type,C源碼如下:(只列出了部分)
PyTypeObjectPyType_Type={
PyVarObject_HEAD_INIT(PyType_Type,0)
"type",/*tp_name*/
sizeof(PyHeapTypeObject),/*tp_basicsize*/
sizeof(PyMemberDef),/*tp_itemsize*/
(destructor)type_dealloc,/*tp_dealloc*/
//...
(reprfunc)type_repr,/*tp_repr*/
//...
內(nèi)建類(lèi)型和自定義類(lèi)對(duì)應(yīng)的PyTypeObject對(duì)象都是通過(guò)這個(gè)PyType_Type創(chuàng)建的。在第二行PyVarObject_HEAD_INIT(PyType_Type,0)中,PyType_Type把自己的ob_type字段設(shè)置成了它自己,即type的類(lèi)型是type
把PyType_Type加入到結(jié)構(gòu)圖中,圖示如下:
5.PyBaseObject_Type:類(lèi)型之基
object是另外一個(gè)特殊的類(lèi)型,它是所有類(lèi)型的基類(lèi)。如果要找到object對(duì)應(yīng)的結(jié)構(gòu)體,我們可以通過(guò)PyFloat_Type的tp_base字段來(lái)尋找,因?yàn)樗赶虻木褪莊loat的基類(lèi)object。但是我們查看源碼發(fā)現(xiàn),PyFloat_Type中并沒(méi)有初始化tp_base字段:
同樣地,我們查看Objects文件夾下的各種不同類(lèi)型所對(duì)應(yīng)的結(jié)構(gòu)體,發(fā)現(xiàn)tp_base字段均沒(méi)有初始化,于是尋找將tp_base字段初始化的函數(shù):
void
_Py_ReadyTypes(void)
if(PyType_Ready(PyBaseObject_Type)0)
Py_FatalError("Can'tinitializeobjecttype");
if(PyType_Ready(PyType_Type)0)
Py_FatalError("Can'tinitializetypetype");
//...
if(PyType_Ready(PyFloat_Type)0)
Py_FatalError("Can'tinitializefloattype");
//...
_Py_ReadyTypes中統(tǒng)一調(diào)用了PyType_Ready()函數(shù),為各種類(lèi)型設(shè)置tp_base字段:
int
PyType_Ready(PyTypeObject*type)
//...
/*Initializetp_base(defaultstoBaseObjectunlessthat'sus)*/
base=type-tp_base;
if(base==NULLtype!=PyBaseObject_Type){
base=type-tp_base=PyBaseObject_Type;
Py_INCREF(base);
//...
可以看到,PyType_Ready在初始化tp_base字段時(shí),對(duì)于PyBaseObject_Type,不會(huì)設(shè)置tp_base字段,即object是沒(méi)有基類(lèi)的,這就是為了保證繼承鏈有一個(gè)終點(diǎn)。
PyBaseObject_Type源碼如下:(只列出了部分)
PyTypeObjectPyBaseObject_Type={
PyVarObject_HEAD_INIT(PyType_Type,0)
"object",/*tp_name*/
sizeof(PyObject),/*tp_basicsize*/
0,/*tp_itemsize*/
object_dealloc,/*tp_dealloc*/
//...
object_repr,/*tp_repr*/
//...
0,/*tp_base*/
//...
源碼解讀:
第二行PyVarObject_HEAD_INIT(PyType_Type,0):把ob_type設(shè)置為PyType_Type,即object的類(lèi)型是type
將PyBaseObject_Type加入到結(jié)構(gòu)圖中,圖示如下:
6.補(bǔ)充
object的類(lèi)型是type,type的基類(lèi)是object。先有雞還是先有蛋?
答:
前面我們提到,在各種類(lèi)型對(duì)應(yīng)的C語(yǔ)言結(jié)構(gòu)體變量初始化的時(shí)候,tp_base字段都是沒(méi)有設(shè)置具體值的,直到_Py_ReadyTypes()函數(shù)執(zhí)行時(shí),才通過(guò)PyType_Ready()去初始化各類(lèi)型的tp_base。
在PyBaseObject_Type初始化時(shí),會(huì)將ob_tyep字段設(shè)置為PyType_Type,即object的類(lèi)型為type;在_Py_ReadyTypes函數(shù)中,會(huì)通過(guò)PyType_Ready()設(shè)置PyType_Type的tp_base字段為PyBaseOb
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年砌筑工考試題庫(kù)及答案
- 學(xué)生定崗實(shí)習(xí)協(xié)議
- 建筑機(jī)械設(shè)備租賃協(xié)議
- 混凝土結(jié)構(gòu)設(shè)計(jì)項(xiàng)目實(shí)戰(zhàn)報(bào)告
- 2025年切割設(shè)備控制系統(tǒng)項(xiàng)目合作計(jì)劃書(shū)
- 煤礦重大隱患自查試題及答案
- 開(kāi)關(guān)電源廠(chǎng)的試題及答案
- 2025年高品質(zhì)H酸合作協(xié)議書(shū)
- 成立護(hù)理質(zhì)控小組
- 2025關(guān)于最大額循環(huán)抵押借款合同
- 2025年湖南電焊考試題庫(kù)
- 2025至2030中國(guó)纖維素納米纖維(CNF)行業(yè)項(xiàng)目調(diào)研及市場(chǎng)前景預(yù)測(cè)評(píng)估報(bào)告
- 檢驗(yàn)標(biāo)準(zhǔn)管理辦法
- 2025年自考毛概考試試題及答案
- 2025-2026教科版科學(xué)三年級(jí)上冊(cè)詳細(xì)教學(xué)計(jì)劃
- 閥門(mén)維修協(xié)議書(shū)范本
- 常用干燥器簡(jiǎn)介二李瑛化工傳熱設(shè)備與操作00課件
- DB32∕T 4514-2023 養(yǎng)老機(jī)構(gòu)等級(jí)評(píng)定工作規(guī)范
- 2025年市政考試網(wǎng)絡(luò)資源試題及答案
- 高邊坡施工信息化管理措施
- 食品召回管理辦法2025培訓(xùn)
評(píng)論
0/150
提交評(píng)論