python3.7源码剖析——python对象
學習陳儒老師的《Python源碼剖析》
 我用的源碼為python3.7,所以做了一些改動
PyObject
在python中萬物皆對象,對象擁有相同的一些內容,這些定義在PyObject中
[object.h] typedef struct _object {_PyObject_HEAD_EXTRAPy_ssize_t ob_refcnt;struct _typeobject *ob_type; } PyObject;_PyObject_HEAD_EXTRA宏 其實在release模式下編譯python不會定義符號PyTRACE_REFS
 所以 #define _PyObject_HEAD_EXTRA 是空白
那么PyObject就變為了
typedef struct _object {Py_ssize_t ob_refcnt;struct _typeobject *ob_type; } PyObject;Py_ssize_t ob_refcnt 跟python的內存管理機制有關,他實現了基于引用計數的垃圾收集機制,當引用計數減少到0時,就可以從堆上被刪除,釋放內存
 
 
 struct _typeobject *ob_type 是一個指向_typeObject結構體指針,他來指定一個對象類型的類型,因為其實相同類型執行操作的操作是一樣的,所以放在ob_type所指向的類型對象的中
當然,每個對象除了這個頭還會有他們特有的一些東西,PyObject對象里面是別的對象共有的,因為對于結構體頭部都是這個的話我們是可以用PyObject*類型的指針輕松訪問到任意結構體的頭部信息中的ob_refcnt與ob_type(只要結構體的頭部固定是這些內容)那么除了這個頭部,其他不同的對象有其他不同的額外東西
[longobject.h] typedef struct _longobject PyLongObject; /* Revealed in longintrepr.h */ [longintrepr.h] struct _longobject {PyObject_VAR_HEADdigit ob_digit[1]; };對于整數來說 他的頭部是一個變長對象的頭部(python3中的整數沒有大小限制,所以源碼中不是單純的用int型去存儲他的值,而是用可以變化大小的動態數組,這個結構體尾部大小會在創建的時候確定大小這里默認是1),這個會根據ob_size屬性的大小來確定大小,ob_size是變成對象(結構體)擁用的成員
定長與變長對象
對于變定長對象來說,他需要的空間是無法確定的,就是你不可能把他的大小寫死,那么這個結構體需要分配的存儲數據那塊的內存大小就是需要根據實際對象的長度改變的
[object.h] typedef struct {PyObject ob_base; //一個定長結構體PyObjectPy_ssize_t ob_size; /* Number of items in variable part */ } PyVarObject;這是變長對象的結構體頭部 可以看出來他的頭部首先是一個定長對象結構體,然后是一個控制長度大小的ob_size, 從頭部來看也就是說變長對象也是可以通過PyObject*去訪問到ob_refcnt,ob_type這兩個屬性的,因為他們的偏移量一樣,ob_size這個成員實際上就是指明了變長對象中一共容納了多少元素
類型對象
[object.h] typedef struct _typeobject {PyObject_VAR_HEADconst char *tp_name; /* For printing, in format "<module>.<name>" */Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation *//* Methods to implement standard operations */destructor tp_dealloc;printfunc tp_print;getattrfunc tp_getattr;setattrfunc tp_setattr;PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)or tp_reserved (Python 3) */reprfunc tp_repr;/* Method suites for standard classes */PyNumberMethods *tp_as_number;PySequenceMethods *tp_as_sequence;PyMappingMethods *tp_as_mapping;...... #ifdef COUNT_ALLOCS/* these must be last and never explicitly initialized */Py_ssize_t tp_allocs;Py_ssize_t tp_frees;Py_ssize_t tp_maxalloc;struct _typeobject *tp_prev;struct _typeobject *tp_next; #endif } PyTypeObject;PyObject_VAR_HEAD 宏
#define PyObject_VAR_HEAD PyVarObject ob_base;可以看出來 type_object對象是一個變長對象的頭部,也就是說它具備ob_size成員,且與PyVarObject一樣頭部可以用PyObject*訪問ob_refcnt, *ob_type
對象的行為
[object.h] typedef struct _typeobject {PyObject_VAR_HEADconst char *tp_name; /* For printing, in format "<module>.<name>" */Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation *//* Methods to implement standard operations */destructor tp_dealloc;printfunc tp_print;getattrfunc tp_getattr;setattrfunc tp_setattr;PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)or tp_reserved (Python 3) */reprfunc tp_repr;/* Method suites for standard classes */PyNumberMethods *tp_as_number;PySequenceMethods *tp_as_sequence;PyMappingMethods *tp_as_mapping;...... } PyTypeObject; PyNumberMethods *tp_as_number; PySequenceMethods *tp_as_sequence; PyMappingMethods *tp_as_mapping;可以從名字上看出這三個方法分別是作為數字的方法,作為序列的方法,作為字典的方法
 這也是為什么在python中其實只要我們實現了特定的方法就可以獲得序列的操作,比如實現__add__方法可以實現加法,__getitem__可以實現序列的相關操作
類型的類型
因為PyTypeObject的頭部是一個PyObject_VAR_HEAD(PyVarObject ob_base)說明它的最頭部還嵌套了一個(PyObject),而PyObject類型里面有一個ob_type指針指向一個PyTypeObject
[object.h] typedef struct _object {_PyObject_HEAD_EXTRAPy_ssize_t ob_refcnt;struct _typeobject *ob_type; } PyObject;類型的類型也就是ob_type指向的還是一個PyTypeObject,下面是他指向的結構體,里面初始化了一些數據
[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 ... };頭部的宏
#define PyObject_HEAD_INIT(type) \{ _PyObject_EXTRA_INIT \1, type },#define PyVarObject_HEAD_INIT(type, size) \{ PyObject_HEAD_INIT(type) size },可以看出來是初始化了PyVarObject頭部的值,默認為
{{ _PyObject_EXTRA_INIT //前面說過是空白的1 // 引用計數為1type: PyType_Type 指向自己} PyObject結構體部分size:0 //變長對象,默認長度給了0 }PyVarObject結構體部分總結
有些是自己的理解,可有錯誤,歡迎大佬們指正~
總結
以上是生活随笔為你收集整理的python3.7源码剖析——python对象的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: java web应用程序_如何构建Jav
- 下一篇: Flex与JavaScript的交互:调
