PyType_Type和PyBaseObject_Type
PyObject和PyTypeObject內容的最后指出下圖中對實例對象和類型對象的理解是不完全正確的,

浮點類型對象全局唯一,Python在C語言層面實現過程中將其定義為一個全局靜態變量,定義于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節的內容。
- 第3行將
tp_name
字段初始化成類型名稱"float"
- 再往下是各種操作的函數指針
ob_type
指針指向PyType_Type
,這也是一個靜態定義的全局變量。代表“類型的類型” 的type對象就是PyType_Type
。
一. 類型的類型—PyType_Tpye(type的實體)
上文中,float類型對象在底層實現過程中對應PyFloat_Type
全局靜態變量。Python類型是一種對象,也有自己的類型,即Python中的type。
>>> float.__class__
class 'type'>
自定義類型也遵循同樣的規則,
>>> class Foo(object):
... pass
...
>>> Foo.__class__
class 'type'>
在查看PyFloat_Type
代碼實現時,ob_type
字段指向的PyType_Type
就是type的實現。在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 */
// ...
};
- 內建類型和自定義類的
PyTypeObject
對象都是通過PyType_Type
創建。PyType_Type
是PyTypeObject
的一個實例。
PyType_Type
是類型機制中至關重要的對象,是所有類型的類型,稱為元類型。
- 第2行代碼處
PyType_Type
將自身的ob_type
字段指向它自己。
>>> type.__class__
class 'type'>
>>> type.__class__ is type
True
由此,以float為例,可以繪制一個更完善但是并不完全正確的實例對象和類型對象在內存中的關系圖,

二. 類型之基—PyBaseObject_Type(object的實體)
上一節中紅色標記的語句,并不完全正確是因為思考過程中忽略了object
對象的存在。
object
是另一個特殊的類型,是所有類型的基類。同樣可以通過PyFloat_Type
中tp_base
字段順藤摸瓜找到。然而,在源碼的第2行的PyVarObject_HEAD_INIT定義中,該字段并沒有初始化,
更進一步查找代碼中PyFloat_Type
出現的地方,在Object/object.c
中發現如下代碼,
if (PyType_Ready(PyFloat_Type) 0)
Py_FatalError("Can't initialize float type");
創建類型對象過程中,需要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
函數初始化PyBaseObject_Type
時,不設置tp_base
字段。 因為繼承鏈必須有一個終點,否則沿著繼承鏈查找時會陷入死循環。
>>> print(object.__base__)
None
由此,得到了實例對象和類型對象在內存中完整的關系圖。以float為例,

到此這篇關于Python源碼學習之PyType_Type和PyBaseObject_Type詳解的文章就介紹到這了,更多相關PyType_Type和PyBaseObject_Type內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- Python源碼學習之PyObject和PyTypeObject
- Python源碼解析之List
- python源碼剖析之PyObject詳解
- python opencv人臉識別考勤系統的完整源碼
- python 制作手機歸屬地查詢工具(附源碼)
- python基于tkinter制作無損音樂下載工具(附源碼)
- Python bsonrpc源碼解讀
- Python制作腳本幫女朋友搶購清空購物車