python源碼剖析筆記1——Python對象初見

來源:互聯網
上載者:User

標籤:python   源碼   基礎   

python源碼剖析筆記1——Python對象初見

工作整兩年了,用python最多,然而對於python內部機制不一定都清楚,每天沉醉於增刪改查的簡單邏輯編寫,實在耗神。很多東西不用就忘記了,比如C語言,正好,python源碼用C寫的,分析python源碼的同時又能溫故C語言基礎,實在是件很好的事情。另外,還有陳儒大神的《python源碼剖析》做指引,分析也不至於沒頭沒腦。期望在一個月的業餘時間,能有所小成,以此為記。

1 python中的對象

python中,一切東西都是對象,在c語言實現中對應著結構體。首先當然還是從python內建對象開始看起,最基本的是PyIntObject, PyStringObject, PyListObject, PyDictObject這幾個,他們分別屬於int,string, list, dict類型。從python2.2之後有了new style class之後,這些內建對象都是繼承自object類型,object在代碼中對應PyBaseObject_Type。比如我們指派陳述式a=3,那麼a就是一個PyIntObject對象,它的類型是int,在代碼中對應PyInt_Type,PyInt_Type也是一種對象,我們稱之為類型對象。那麼PyInt_Type它的類型是什麼呢,答案是type, 對應到代碼中就是PyType_Type。當然object也是一個類型對象,它的類型也是PyType_Type。這麼一層層下去,PyType_Type也是個對象,那它的類型又是什麼呢,沒錯,答案就是它的類型就是它自己,。看下面的驗證代碼:

##內建對象測試In [1]: a = 3In [2]: type(a)Out[2]: intIn [3]: type(int)Out[3]: typeIn [4]: type(type)Out[4]: typeIn [5]: int.__base__Out[5]: objectIn [6]: type(object)Out[6]: type

先分析下幾個基礎內建對象在C語言中的結構體以及常用的幾個宏,為了方便,我用的也是陳儒大神分析的那個版本一致,版本是2.5.6.源碼官網有下載。

// 內建對象基礎#define PyObject_HEAD                   \        Py_ssize_t ob_refcnt;                   struct _typeobject *ob_type;#define PyObject_HEAD_INIT(type)        \        1, type,#define PyObject_VAR_HEAD               \        PyObject_HEAD                           Py_ssize_t ob_size; /* Number of items in variable part */#define Py_INVALID_SIZE (Py_ssize_t)-1typedef struct _object {        PyObject_HEAD} PyObject;typedef struct {        PyObject_VAR_HEAD} PyVarObject;typedef struct _typeobject {        PyObject_VAR_HEAD        const char *tp_name; /* For printing, in format "<module>.<name>" */        Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */        destructor tp_dealloc;        printfunc tp_print;        getattrfunc tp_getattr;        setattrfunc tp_setattr;        cmpfunc tp_compare;        reprfunc tp_repr;        ...} PyTypeObject;typedef struct {    PyObject_HEAD    long ob_ival;} PyIntObject;typedef struct {    PyObject_VAR_HEAD    long ob_shash;    int ob_sstate;    char ob_sval[1];    /* Invariants:     *     ob_sval contains space for ‘ob_size+1‘ elements.     *     ob_sval[ob_size] == 0.     *     ob_shash is the hash of the string or -1 if not computed yet.     *     ob_sstate != 0 iff the string object is in stringobject.c‘s     *       ‘interned‘ dictionary; in this case the two references     *       from ‘interned‘ to this object are *not counted* in ob_refcnt.     */} PyStringObject;

如代碼中所示,PyObject是所有Python對象的基石,所有後續看到的對象都有一個相同的PyObject頭部,從而我們可以在源碼中看到所有的對象都可以用PyObject*指標指向,這就是物件導向中經常用到的多態的技巧了。Python內部各個函數對象間也是通過PyObject*傳遞,即便本身這是一個PyIntObject類型的對象,代碼中並不會用PyIntObject*指標進行傳遞,這也是為了實現多態。比如下面的函數:

void Print(PyObject* object) {    object->ob_type->tp_print(object);}

另外如代碼中注釋所說的,變長對象的ob_size指的是元素個數,不是位元組數目。

2 python對象引用計數

下面是幾個常用的操作對象引用計數的宏定義(object.h),一併列出,這裡去除了一些調試時用的代碼,更容易看明白代碼含義。Py_NewReference是初始化時對象時設定引用計數, Py_INCREF和Py_DECREF分別用來增加引用技術和減少引用計數。從代碼中可以看到,python增加引用和減少引用都是通過這些宏操作的,**有一點需要注意的是,當對象引用ob_refcnt減小到0時,會調用對象的解構函式,解構函式並不一定會調用free釋放記憶體空間,因為頻繁申請和釋放記憶體嚴重影響效能,所以在後面看到python有大量用到記憶體池技術,對提升效能有很大效果。

需要說明的是,類型對象是不在引用計數規則之中的,每個對象指向類型對象的指標並不視為類型對象的引用,也就是說不會影響類型對象的引用計數,類型對象永遠不會被析構。

#define _Py_NewReference(op) ((op)->ob_refcnt = 1)#define _Py_Dealloc(op) (*(op)->ob_type->tp_dealloc)((PyObject *)(op)))#define Py_INCREF(op) ((op)->ob_refcnt++)#define Py_DECREF(op)                                   \        if (--(op)->ob_refcnt != 0)                                 ;        else                                                        _Py_Dealloc((PyObject *)(op))#define Py_CLEAR(op)                                    do {                                                    if (op) {                                               PyObject *tmp = (PyObject *)(op);                               (op) = NULL;                                    Py_DECREF(tmp);                         }                                       } while (0)/* Macros to use in case the object pointer may be NULL: */#define Py_XINCREF(op) if ((op) == NULL) ; else Py_INCREF(op)#define Py_XDECREF(op) if ((op) == NULL) ; else Py_DECREF(op)
3 Python對象分類

python中的對象大致可以分為下面幾類:
- 數值對象:如integer,float,boolean
- 序列集合對象:如string,list,tuple
- 字典對象:如dict
- 類型對象:如type
- 內部對象:如後面會看到的code,function,frame,module以及method對象等。

4 參考資料
  • 《python源碼剖析》

python源碼剖析筆記1——Python對象初見

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.