您好,登錄后才能下訂單哦!
這篇文章主要講解了“在python中PyType_Type和PyBaseObject_Type有什么區(qū)別”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“在python中PyType_Type和PyBaseObject_Type有什么區(qū)別”吧!
PyObject和PyTypeObject內(nèi)容的最后指出下圖中對實例對象和類型對象的理解是不完全正確的,
浮點類型對象全局唯一,Python在C語言層面實現(xiàn)過程中將其定義為一個全局靜態(tài)變量,定義于Object/floatobject.c
中,命名為PyFloat_Type
。
PyTypeObject PyFloat_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "float", sizeof(PyFloatObject), 0, (destructor)float_dealloc, /* tp_dealloc */ // ... (reprfunc)float_repr, /* tp_repr */ // ... };
第2行使用初始化ob_refcnt
、ob_type
以及ob_size
三個字段,PyVarObject_HEAD_INIT
的定義可以參考博文1.4.3節(jié)的內(nèi)容。
第3行將tp_name
字段初始化成類型名稱"float"
再往下是各種操作的函數(shù)指針
ob_type
指針指向PyType_Type
,這也是一個靜態(tài)定義的全局變量。代表“類型的類型” 的type對象就是PyType_Type
。
上文中,float類型對象在底層實現(xiàn)過程中對應(yīng)PyFloat_Type
全局靜態(tài)變量。Python類型是一種對象,也有自己的類型,即Python中的type。
>>> float.__class__ <class 'type'>
自定義類型也遵循同樣的規(guī)則,
>>> class Foo(object): ... pass ... >>> Foo.__class__ <class 'type'>
在查看PyFloat_Type
代碼實現(xiàn)時,ob_type
字段指向的PyType_Type
就是type的實現(xiàn)。在Object/typeobject.c
中定義,
PyTypeObject PyType_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)建類型和自定義類的PyTypeObject
對象都是通過PyType_Type
創(chuàng)建。PyType_Type
是PyTypeObject
的一個實例。
PyType_Type
是類型機制中至關(guān)重要的對象,是所有類型的類型,稱為元類型。
第2行代碼處PyType_Type
將自身的ob_type
字段指向它自己。
>>> type.__class__ <class 'type'> >>> type.__class__ is type True
由此,以float為例,可以繪制一個更完善但是并不完全正確的實例對象和類型對象在內(nèi)存中的關(guān)系圖,
上一節(jié)中紅色標(biāo)記的語句,并不完全正確是因為思考過程中忽略了object
對象的存在。
object
是另一個特殊的類型,是所有類型的基類。同樣可以通過PyFloat_Type
中tp_base
字段順藤摸瓜找到。然而,在源碼的第2行的PyVarObject_HEAD_INIT定義中,該字段并沒有初始化,
0, /* tp_base */
更進一步查找代碼中PyFloat_Type
出現(xiàn)的地方,在Object/object.c
中發(fā)現(xiàn)如下代碼,
if (PyType_Ready(&PyFloat_Type) < 0) Py_FatalError("Can't initialize float type");
創(chuàng)建類型對象過程中,需要PyType_Ready
方法將tp_base
字段初始化,具體如下
int PyType_Ready(PyTypeObject *type) { // ... base = type->tp_base; if (base == NULL && type != &PyBaseObject_Type) { base = type->tp_base = &PyBaseObject_Type; Py_INCREF(base); } // ... }
PyFloat_Type
中的tp_base
字段初始化成PyBaseObject_Type
,它就是object背后的實體,其源碼定義為,
PyTypeObject PyBaseObject_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 */ };
源碼中ob_type
字段指向PyType_Type
這與下方object在 Python中的測試代碼相吻合,
>>> object.__class__ <class 'type'>
此外,PyType_Ready
函數(shù)初始化PyBaseObject_Type
時,不設(shè)置tp_base
字段。 因為繼承鏈必須有一個終點,否則沿著繼承鏈查找時會陷入死循環(huán)。
>>> print(object.__base__) None
由此,得到了實例對象和類型對象在內(nèi)存中完整的關(guān)系圖。以float為例,
感謝各位的閱讀,以上就是“在python中PyType_Type和PyBaseObject_Type有什么區(qū)別”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對在python中PyType_Type和PyBaseObject_Type有什么區(qū)別這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。