本來想寫python type object之間的區別,聯繫,可是看着寫着,發現東西太多,因而分幾個部分來寫吧,這是第一部分,python中的萬物理論,對象python
python中一切皆對象,不管是一個數字或一個字符串或一個類或一個類實例等都是對象,那麼對象究竟是什麼,來看object.h源碼文件中對於對象的描述:git
在Python中,對象就是爲C中的結構體在堆上申請的一塊內存。通常來講,對象是不能被靜態初始化的,而且也不能在棧空間上生存。惟一的例外是類型對象,Python中全部的內建類型對象都是被靜態初始化的。github
在Python中,一個對象一旦被建立,它在內存中的大小就是不變的了。這就意味着那些須要容納可變長度數據的對象只能在對象內維護一個指向一塊可變大小的內存區域的指針。python2.7
一個對象維護着一個「引用計數」,其在一個指向這個對象的指針複製或刪除時增長或減小。當這個引用計數變爲零時,也就是說已經沒有任何指向這個對象的引用,這個對象就能夠從堆上被移除。spa
一個對象有着一個類型(type),來肯定它表明和包含什麼類型的數據。一個對象的類型在它被建立時是固定的。類型自己也是對象。一個對象包含一個指向與之相配的類型的指針。類型本身也有一個類型指針指向着一個表示類型對象的類型的對象「type」,這個type對象也包括一個類型指針,不過是指向它本身的。指針
基本上Python對象的特性就是這些,那麼,在C的層面上,一個Python對象的這些特性是如何實現的呢?code
python中一切皆對象,全部對象都基於PyObject,都有共同的內容定義,這些內容在object.h中大約106行定義。對象
typedef struct _object { _PyObject_HEAD_EXTRA Py_ssize_t ob_refcnt; struct _typeobject *ob_type; } PyObject;
閱讀以上代碼,咱們會發現:內存
在Python2中,一個int類型的對象的值在C中的類型是不變的(int),因此它在內存中佔據的大小也是不變的。可是一個字符串對象事先咱們根本不可能知道它所維護的值的大小。在C中,根本就沒有「一個字符串」的概念,字符串對象應該維護「n個char型變量」。不僅是字符串,list等對象也應該維護「n個PyObject對象」。這種「n個……」也是一類Python對象的共同特徵,所以,Python在PyObject以外,還有一個表示這類對象的結構體-PyVarObject,在object.h中大約112行定義。:字符串
typedef struct { PyObject ob_base; Py_ssize_t ob_size; /* Number of items in variable part */ } PyVarObject;
咱們把相似Python2中的int對象這樣不包含可變長度的對象稱爲「定長對象」,而字符串對象這樣包含可變長度數據的對象稱爲「變長對象」。
爲何要強調Python2中的int對象呢?由於在Python3中,int類型的底層實現直接使用了Python2中的long類型的底層實現,也就是說,如今的int是之前的long類型,而之前的int類型已經不復存在。而long類型實際是一個變長對象。
變長對象一般都是容器,ob_size這個成員實際上就是指明瞭變長對象中一共容納了多少個元素,即前面講的「n個......」。
從PyVarObject的定義能夠看出,變長對象實際就是在PyObject對象後面加了個ob_size,所以,對於任意一個PyVarObject,其所佔用的內存開始部分的字節就是一個PyObject。在Python內部,每個對象都擁有着相同的對象頭部。這就使得在Python中,對對象的引用變得很是的統一,咱們只須要用一個PyObject *指針就能夠引用任意的一個對象。