閱讀878 返回首頁    go Python


Python 源碼閱讀:類型

這篇主要涉及Python對象的類型機製

有點繞, 一定要思維清晰的時候再看哦:)

一個例子

1

>>>type(a)

#等價的兩個

>>>type(type(a))

>>>type(int)

#還是等價的兩個

>>>type(type(type(a)))

>>>type(type(int))

我們反向推導一個int對象是怎麼生成的.

1. 首先, 定義一種類型叫PyTypeObject

代碼位置 Include/object.h

定義

typedefstruct_typeobject{

/* MARK: base, 注意, 是個變長對象*/

PyObject_VAR_HEAD

constchar*tp_name;/* For printing, in format "." *///類型名

Py_ssize_ttp_basicsize,tp_itemsize;/* For allocation */// 創建該類型對象時分配的內存空間大小

// 一堆方法定義, 函數和指針

/* Methods to implement standard operations */

printfunctp_print;

hashfunctp_hash;

/* Method suites for standard classes */

PyNumberMethods *tp_as_number;// 數值對象操作

PySequenceMethods *tp_as_sequence;// 序列對象操作

PyMappingMethods *tp_as_mapping;// 字典對象操作

// 一堆屬性定義

....

}PyTypeObject;

說明

1.tp_name

類型名,這裏是"type"

2.PyVarObject_HEAD_INIT(&PyType_Type,)

PyVarObject_HEAD_INIT,這個方法在Include/object.h中,

等價於

ob_refcnt=1

*ob_type= &PyType_Type

ob_size=

即,PyType_Type的類型是其本身!1.tp_name

類型名,這裏是"type"

2.PyVarObject_HEAD_INIT(&PyType_Type,)

PyVarObject_HEAD_INIT,這個方法在Include/object.h中,

等價於

ob_refcnt=1

*ob_type= &PyType_Type

ob_size=

即,PyType_Type的類型是其本身!

所有Type都是PyTypeObject的”實例”: PyType_Type/PyInt_Type

2. 然後, 用PyTypeObject初始化得到一個對象PyType_Type

代碼位置 Objects/typeobject.c

定義

PyTypeObjectPyType_Type={

PyVarObject_HEAD_INIT(&PyType_Type,)

"type",/* tp_name */

sizeof(PyHeapTypeObject),/* tp_basicsize */

sizeof(PyMemberDef),/* tp_itemsize */

(destructor)type_dealloc,/* tp_dealloc */

// type對象的方法和屬性初始化值

.....

};

說明

1.tp_name

類型名,這裏是"type"

2.PyVarObject_HEAD_INIT(&PyType_Type,)

PyVarObject_HEAD_INIT,這個方法在Include/object.h中,

等價於

ob_refcnt=1

*ob_type= &PyType_Type

ob_size=

即,PyType_Type的類型是其本身!1.tp_name

類型名,這裏是"type"

2.PyVarObject_HEAD_INIT(&PyType_Type,)

PyVarObject_HEAD_INIT,這個方法在Include/object.h中,

等價於

ob_refcnt=1

*ob_type= &PyType_Type

ob_size=

即,PyType_Type的類型是其本身!1.tp_name

類型名,這裏是"type"

2.PyVarObject_HEAD_INIT(&PyType_Type,)

PyVarObject_HEAD_INIT,這個方法在Include/object.h中,

等價於

ob_refcnt=1

*ob_type= &PyType_Type

ob_size=

即,PyType_Type的類型是其本身!

結構

第一張圖, 箭頭表示實例化(google doc用不是很熟找不到對應類型的箭頭)

第二張圖, 箭頭表示指向

使用

# 1. int 的 類型 是`type`

>>>type(int)

# 2. type 的類型 還是`type`, 對應上麵說明第二點

>>>type(type(int))

注意: 無論任何時候, ob_type指向的是 PyTypeObject的實例: PyType_Type/PyInt_Type…

3. 再然後, 定義具體的類型, 這裏以PyInt_Type為例子

代碼位置 Objects/intobject.c

定義

PyTypeObjectPyInt_Type={

PyVarObject_HEAD_INIT(&PyType_Type,)

"int",

sizeof(PyIntObject),

,

// int類型的相關方法和屬性值

....

(hashfunc)int_hash,/* tp_hash */

};

說明

1."int"

PyInt_Type的類型名是int

2.PyVarObject_HEAD_INIT(&PyType_Type,)

PyInt_Type的

*ob_type= &PyType_Type

結構

使用

>>>type(1)

>>>type(type(1))

4. 最後, 生成一個整數對象int

代碼位置 Include/intobject.h

定義

typedefstruct{

PyObject_HEAD

longob_ival;

}PyIntObject;

結構

1.PyIntObject為整數類型

2.聲明一個整數後得到整數對象

3.對象ob_type指向PyInt_type對象

到這裏, 總結下

1.一切都是對象

2.PyType_Type/PyInt_Type/PyString_Type....等

這些是`類型對象`,可以認為是同級,都是PyTypeObject這種`類型`的實例!

3.雖然是同級,

但是其他PyXXX_Type,其類型指向PyType_Type

PyType_Type的類型指向自己,它是所有類型的`類型`

4.PyTypeObject是一個變長對象

5.每個object,例如PyIntObject都屬於一種`類型`

object初始化時進行關聯

多態是如何實現的?

對象的多態, 例如hash

>>>hash(1)

1

>>>hash("abc")

從上麵數據結構可以看到, 方法及屬性, 在不同Type實例化時就確定了

PyTypeObjectPyInt_Type={

...

(hashfunc)int_hash,/* tp_hash */

...

}

PyTypeObjectPyString_Type={

...

(hashfunc)string_hash,/* tp_hash */

...

}

Python內部傳遞的是泛型指針PyObject *, 函數調用時, 找到其類型* ob_type, 然後調用

object -> ob_type -> tp_hash

即: 大量函數指針決定了該類型的具體行為

來源:wklken

編輯 | 碼哥

圖片源於網絡,版權歸原作者所有

最後更新:2017-10-09 00:53:52

  上一篇:go 國慶去哪裏人最多?用 Python 抓取的熱力圖告訴你!
  下一篇:go Python老司機收藏夾的17個國外免費學習網站