自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳解 Python 源碼之對(duì)象機(jī)制

移動(dòng)開發(fā)
在Python中,對(duì)象就是在堆上申請(qǐng)的結(jié)構(gòu)體,對(duì)象不能是被靜態(tài)初始化的,并且也不能是在??臻g上生存的。唯一的例外就是類型對(duì)象(type object),Python中所有的類型對(duì)象都是被靜態(tài)初始化的。

本篇文章主要是對(duì)Python 進(jìn)行詳解,內(nèi)容是介紹Python 源碼之對(duì)象機(jī)制,先來(lái)看內(nèi)容。

1、對(duì)象

Python的世界中,一切都是對(duì)象,一個(gè)整數(shù)是一個(gè)對(duì)象,一個(gè)字符串也是一個(gè)對(duì)象,更為奇妙的是,類型也是一個(gè)對(duì)象,整數(shù)類型是一個(gè)對(duì)象,字符串類型也是一個(gè)對(duì)象。從1980年Guido在那個(gè)圣誕節(jié)揭開Python世界的大幕開始,一直到現(xiàn)在,Python經(jīng)歷了一次一次的升級(jí),但是其實(shí)現(xiàn)語(yǔ)言一直都是ANSI C。我們知道,C并不是一個(gè)面向?qū)ο蟮恼Z(yǔ)言,那么在Python中,它的對(duì)象機(jī)制是如何實(shí)現(xiàn)的呢?

對(duì)于人的思維來(lái)說(shuō),對(duì)象是一個(gè)比較形象的概念,而對(duì)于計(jì)算機(jī)來(lái)說(shuō),對(duì)象實(shí)際上是一個(gè)抽象的概念。計(jì)算機(jī)并不能理解這是一個(gè)整數(shù),那是一個(gè)字符串,對(duì)于計(jì)算機(jī)來(lái)說(shuō),它所知道的一切都是字節(jié)。通常的說(shuō)法是,對(duì)象是數(shù)據(jù)以及基于這些數(shù)據(jù)的操作的集合。在計(jì)算機(jī)上,一個(gè)對(duì)象實(shí)際上就是一片被分配的內(nèi)存空間,這些內(nèi)存可能是連續(xù)的,也有可能是離散的,這都不重要,重要的是這片內(nèi)存在更高的層次上可以作為一個(gè)整體來(lái)考慮,這個(gè)整體就是一個(gè)對(duì)象。在這片內(nèi)存中,存儲(chǔ)著一系列的數(shù)據(jù)以及可以對(duì)這些數(shù)據(jù)進(jìn)行修改或讀取的一系列操作的代碼。

Python中,對(duì)象就是在堆上申請(qǐng)的結(jié)構(gòu)體,對(duì)象不能是被靜態(tài)初始化的,并且也不能是在??臻g上生存的。唯一的例外就是類型對(duì)象(type object),Python中所有的類型對(duì)象都是被靜態(tài)初始化的。

Python中,一個(gè)對(duì)象一旦被創(chuàng)建,它在內(nèi)存中的大小就是不變的了。這就意味著那些需要容納可變長(zhǎng)度數(shù)據(jù)的對(duì)象只能在對(duì)象內(nèi)維護(hù)一個(gè)指向一個(gè)可變大小的內(nèi)存區(qū)域的指針。為什么要設(shè)定這樣一條特殊的規(guī)則呢,因?yàn)樽裱@樣的規(guī)則可以使通過(guò)指針維護(hù)對(duì)象的工作變得非常的簡(jiǎn)單。因?yàn)橐坏┰试S對(duì)象的大小可在運(yùn)行期改變,我們可以考慮如下的情形。在內(nèi)存中有對(duì)象A,并且其后緊跟著對(duì)象B。如果運(yùn)行期某個(gè)時(shí)刻,A的大小增大了,這意味著必須將整個(gè)A移動(dòng)到內(nèi)存中的其他位置,否則A增大的部分將覆蓋原本屬于B的數(shù)據(jù)。一旦將A移動(dòng)到內(nèi)存中的其他位置,那么所有指向A的指針必須立即得到更新,光是想一想,就知道這樣的工作是多么的恐怖。

Python中,所有的東西都是對(duì)象,而所有的對(duì)象都擁有一些相同的內(nèi)容,這些內(nèi)容在PyObject中定義,PyObject是整個(gè)Python對(duì)象機(jī)制的核心。

  1. [object.h]   
  2. typedef struct _object {   
  3. PyObject_HEAD   
  4. } PyObject;  

實(shí)際上,PyObject是Python中不包含可變長(zhǎng)度數(shù)據(jù)的對(duì)象的基石,而對(duì)于包含可變長(zhǎng)度數(shù)據(jù)的對(duì)象,它的基石是PyVarObject:

  1. [object.h]   
  2. typedef struct {    PyObject_VAR_HEAD} PyVarObject; 

這兩個(gè)結(jié)構(gòu)體構(gòu)成了Python對(duì)象機(jī)制的核心基石,從代碼中我們可以看到,Python的對(duì)象的秘密都隱藏在PyObject_HEAD與PyObject_VAR_HEAD中。

  1. [object.h]   
  2.  
  3. #ifdef Py_TRACE_REFS  
  4. /* Define pointers to support a doubly-linked list of all live heap objects. */  
  5. #define _PyObject_HEAD_EXTRA \      
  6. struct _object *_ob_next;   \  
  7.     struct _object *_ob_prev;  
  8. #define _PyObject_EXTRA_INIT 0, 0,#else#define _PyObject_HEAD_EXTRA#define _PyObject_EXTRA_INIT#endif  
  9. /* PyObject_HEAD defines the initial segment of every PyObject. */  
  10. #define PyObject_HEAD          \      
  11. _PyObject_HEAD_EXTRA        \  
  12.     int ob_refcnt;  \      
  13. struct _typeobject *ob_type;#define PyObject_VAR_HEAD       \   
  14.    PyObject_HEAD           \      
  15. int ob_size;  
  16.  /* Number of items in variable part */ 

在PyObject_HEAD中定義了每一個(gè)Python對(duì)象都必須有的內(nèi)容,這些內(nèi)容將出現(xiàn)在每一個(gè)Python對(duì)象所占有的內(nèi)存的最開始的字節(jié)中,從PyObject_VAR_HEAD的定義可以看出,即使對(duì)于擁有可變大小數(shù)據(jù)的對(duì)象,其最開始的字節(jié)也含有相同的內(nèi)容,這就是說(shuō),在Python中,每一個(gè)對(duì)象都擁有相同的對(duì)象頭部。這就使得在Python中,對(duì)對(duì)象的引用變得非常的統(tǒng)一,我們只需要用一個(gè)PyObject *就可以引用任意的一個(gè)對(duì)象,而不論該對(duì)象實(shí)際是一個(gè)什么對(duì)象。

在PyObject_HEAD的定義中,我們注意到有一個(gè)ob_refcnt的整形變量,這個(gè)變量的作用是實(shí)現(xiàn)引用計(jì)數(shù)機(jī)制。對(duì)于某一個(gè)對(duì)象A,當(dāng)有一個(gè)新的PyObject *引用該對(duì)象時(shí),A的引用計(jì)數(shù)應(yīng)該增加;而當(dāng)這個(gè)PyObject *被刪除時(shí),A的引用計(jì)數(shù)應(yīng)該減少。當(dāng)A的引用計(jì)數(shù)減少到0時(shí),A就可以從堆上被刪除,以釋放出內(nèi)存供別的對(duì)象使用。

在PyObject_HEAD中,我們注意到ob_type是一個(gè)指向_typeobject結(jié)構(gòu)體的指針,那么這個(gè)結(jié)構(gòu)體是一個(gè)什么東西呢?實(shí)際上這個(gè)結(jié)構(gòu)體也是一個(gè)對(duì)象,它是用來(lái)指定一個(gè)對(duì)象類型的類型對(duì)象。這個(gè)類型對(duì)象我們將在后邊詳細(xì)地考察?,F(xiàn)在我們看到了,在Python中實(shí)際上對(duì)象機(jī)制的核心非常的簡(jiǎn)單,一個(gè)是引用計(jì)數(shù),一個(gè)就是類型。

而對(duì)于擁有可變長(zhǎng)度數(shù)據(jù)的對(duì)象,這樣的對(duì)象通常都是容器,我們可以在PyObject_VAR_HEAD中看到ob_size這個(gè)變量,這個(gè)變量實(shí)際上就是指明了該對(duì)象中一共包含了多少個(gè)元素。注意,ob_size指明的是元素的個(gè)數(shù),而不是字節(jié)的數(shù)目。比如對(duì)于Python中最常用的list,它就是一個(gè)PyVarObject對(duì)象,如果某一時(shí)刻,這個(gè)list中有5個(gè)元素,那么PyVarObject.ob_size的值就是5。

#p#

2、類型對(duì)象

在上面的描述中,我們看到了Python中所有對(duì)象的對(duì)象頭的定義。所以,當(dāng)內(nèi)存中存在某一個(gè)Python的對(duì)象時(shí),該對(duì)象的開始的幾個(gè)字節(jié)的含義一定會(huì)符合我們的預(yù)期。但是,當(dāng)我們把眼光沿著時(shí)間軸上溯,就會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題。當(dāng)在內(nèi)存中分配空間,創(chuàng)建對(duì)象的時(shí)候,毫無(wú)疑問(wèn)地,必須要知道申請(qǐng)多大的空間。顯然,這不會(huì)是一個(gè)定值,因?yàn)閷?duì)于不同的對(duì)象,需要不同的空間,一個(gè)整數(shù)對(duì)象和一個(gè)字符串對(duì)象所需的空間肯定不同。那么,對(duì)象所需的內(nèi)存空間的大小的信息到底在哪里呢?在對(duì)象頭中顯然沒有這樣的信息。

實(shí)際上,內(nèi)存空間大小這樣的對(duì)象的元信息是與對(duì)象所屬類型密切相關(guān)的,因此它一定會(huì)出現(xiàn)在與對(duì)象所對(duì)應(yīng)的類型對(duì)象中?,F(xiàn)在我們可以來(lái)詳細(xì)考察一下類型對(duì)象_typeobject: 

  1. [object.h]   
  2.  
  3. typedef struct _typeobject {  
  4.     PyObject_VAR_HEAD    char *tp_name;  
  5.  /* For printing, in format "<module>.<name>" */   
  6.    int tp_basicsize, tp_itemsize;  
  7.  /* For allocation */  
  8.     /* Methods to implement standard operations */  
  9.     destructor tp_dealloc;printfunc tp_print;  
  10. ……  
  11.     /* More standard operations (here for binary compatibility) */  
  12.     hashfunc tp_hash;   
  13.    ternaryfunc tp_call;  
  14.     ……  
  15. }   
  16. PyTypeObject; 

在_typeobject的定義中包含了許多的信息,主要可以分為四類:

1、類型名,tp_name,主要是Python內(nèi)部以及調(diào)試的時(shí)候使用;

2、創(chuàng)建該類型對(duì)象是分配內(nèi)存空間的大小的信息,即tp_basicsize和tp_itemsize;

3、與該類型對(duì)象相關(guān)聯(lián)的操作信息,比如hashfunc,tp_hash就指明對(duì)于該類型的對(duì)象,如何生成其hash值。在Object.h中可以看到,hashfunc實(shí)際上是一個(gè)函數(shù)指針:typedef long (*hashfunc)(PyObject *); 在_typeobject中,包含了大量的函數(shù)指針,這些函數(shù)指針將用來(lái)指定某個(gè)類型的操作信息。這些操作主要分為標(biāo)準(zhǔn)操作(dealloc, print, compare),標(biāo)準(zhǔn)操作族(numbers, sequences, mappings),以及其他操作(hash, buffer, call…)。

4、我們?cè)谙逻厡⒁枋龅念愋偷念愋托畔ⅰ?/p>

有趣的是我們?cè)赺typeobject的頭部發(fā)現(xiàn)了PyObject_VAR_HEAD,這意味著類型實(shí)際上也是一個(gè)對(duì)象。我們知道在Python中,每一個(gè)對(duì)象都是對(duì)應(yīng)一種類型的,那么一個(gè)有趣的問(wèn)題就出現(xiàn)了,類型對(duì)象的類型是什么呢?這個(gè)問(wèn)題聽上去很繞口,實(shí)際上確非常重要,對(duì)于其他的對(duì)象,可以通過(guò)與其關(guān)聯(lián)的類型對(duì)象確定其類型,那么通過(guò)什么來(lái)確定一個(gè)對(duì)象是類型對(duì)象呢?答案就是PyType_Type:

  1. [typeobject.c]   
  2.  
  3. PyTypeObject PyType_Type = {  
  4.     PyObject_HEAD_INIT(&PyType_Type)    0,  
  5.                   /* ob_size */    "type",  
  6.                  /* tp_name */    sizeof(PyHeapTypeObject),  
  7.        /* tp_basicsize */    sizeof(PyMemberDef),  
  8.             /* tp_itemsize */    ……    PyObject_GC_Del,  
  9.                 /* tp_free */    (inquiry)type_is_gc,  
  10.             /* tp_is_gc */}; 

前面提到,在Python中,每一個(gè)對(duì)象它的開始部分都是一樣的。每一個(gè)對(duì)象都將自己的引用計(jì)數(shù),類型信息保存在開始的部分中。為了方便對(duì)這部分內(nèi)存的初始化,Python中提供了幾個(gè)有用的宏:

  1. [object.h]#ifdef Py_TRACE_REFS#define _PyObject_EXTRA_INIT 0, 0,#else#define _PyObject_EXTRA_INIT#endif#define PyObject_HEAD_INIT(type)    \
  2.    _PyObject_EXTRA_INIT        \   
  3.    1, type, 

再回顧一下PyObject和PyVarObject的定義,初始化的動(dòng)作就一目了然了。實(shí)際上,這些宏在類型對(duì)象的初始化中被大量地使用著。

如果以一個(gè)整數(shù)對(duì)象為例,可以更清晰地看到一半的類型對(duì)象和這個(gè)特立獨(dú)行的PyType_Type對(duì)象之間的關(guān)系:

  1. [intobject.c]   
  2. PyTypeObject PyInt_Type = {  
  3.     PyObject_HEAD_INIT(&PyType_Type)    0,  
  4.     "int",  
  5.     sizeof(PyIntObject),  
  6.     ……  
  7. }; 

現(xiàn)在我們可以放飛想象,看到一個(gè)整數(shù)對(duì)象在運(yùn)行時(shí)的抽象的表示了,下圖中的箭頭表示ob_type:

詳解 Python 源碼之對(duì)象機(jī)制 

#p#

3、對(duì)象間的繼承和多態(tài)

通過(guò)PyObject和類型對(duì)象,Python利用C語(yǔ)言完成了C++所提供的繼承和多態(tài)的特性。前面提到,在Python中所有的內(nèi)建對(duì)象(PyIntObject等)和內(nèi)部使用對(duì)象(PyCodeObject等)的最開始的內(nèi)存區(qū)域都擁有一個(gè)PyObject。實(shí)際上,這一點(diǎn)可以視為PyIntObject,PyCodeObject等對(duì)象都是從PyObject繼承而來(lái)。

在Python創(chuàng)建一個(gè)對(duì)象,比如PyIntObject對(duì)象時(shí),會(huì)分配內(nèi)存,進(jìn)行初始化。然后這個(gè)對(duì)象會(huì)由一個(gè)PyObject*變量來(lái)維護(hù),而不是通過(guò)一個(gè)PyIntObject*指針來(lái)維護(hù)。其它對(duì)象也與此類似,所以在Python內(nèi)部各個(gè)函數(shù)之間傳遞的都是一種范型指針PyObject*。這個(gè)指針?biāo)傅膶?duì)象究竟是什么類型的,不知道,只能從指針?biāo)笇?duì)象的ob_type域判斷,而正是通過(guò)這個(gè)域,Python實(shí)現(xiàn)了多態(tài)機(jī)制。

考慮下面的代碼:

  1. void Print(PyObject* object)   
  2. {   
  3. object->ob_type->tp_print(object);   
  4. }  

如果傳給Print的指針實(shí)際是一個(gè)PyIntObject*,那么就會(huì)調(diào)用PyIntObject對(duì)象對(duì)應(yīng)的類型對(duì)象中定義的輸出操作,如果傳給Print的指針實(shí)際是一個(gè)PyStringObject*,那么就會(huì)調(diào)用PyStringObject對(duì)象對(duì)應(yīng)的類型對(duì)象中定義的輸出操作??梢钥吹?,這里同一個(gè)函數(shù)在不同情況下表現(xiàn)出了不同的行為,這正是多態(tài)的核心所在。

在object.c中,Python實(shí)現(xiàn)了一些對(duì)于類型對(duì)象中的各種操作的簡(jiǎn)單包裝,從而為Python運(yùn)行時(shí)提供了一個(gè)統(tǒng)一的多態(tài)接口層:

  1. [object.c]   
  2. long PyObject_Hash(PyObject *v)   
  3. {   
  4. PyTypeObject *tp = v->ob_type;   
  5. if (tp->tp_hash != NULL)   
  6. return (*tp->tp_hash)(v);   
  7.     ……   
  8. }  

4、引用計(jì)數(shù)

在C或C++中,程序員被賦予了極大的自由,可以任意地申請(qǐng)內(nèi)存。但是權(quán)利的另一面則對(duì)應(yīng)著責(zé)任,程序員必須自己負(fù)責(zé)將申請(qǐng)的內(nèi)存釋放,并釋放無(wú)效指針??梢哉f(shuō),這一點(diǎn)正是萬(wàn)惡之源,大量的內(nèi)存泄露和懸空指針的bug由此而生,如黃河泛濫一發(fā)不可收拾 :)

現(xiàn)代的開發(fā)語(yǔ)言中一般都選擇由語(yǔ)言本身負(fù)責(zé)內(nèi)存的管理和維護(hù),即采用了垃圾收集機(jī)制,比如Java和C#。垃圾收集機(jī)制使開發(fā)人員從維護(hù)內(nèi)存分配和清理的繁重工作中解放出來(lái),但同時(shí)也剝奪了程序員與內(nèi)存親密接觸的機(jī)會(huì),并付出了一定的運(yùn)行時(shí)效率作為代價(jià)。現(xiàn)在看來(lái),隨著垃圾收集機(jī)制的完善,對(duì)時(shí)間要求不是非常高的程序完全可以通過(guò)使用垃圾收集機(jī)制的語(yǔ)言來(lái)完成,這部分程序占了這個(gè)星球上大多數(shù)的程序。這樣做的好處是提高了開發(fā)效率,并降低了bug發(fā)生的機(jī)率。Python同樣也內(nèi)建了垃圾收集機(jī)制,代替程序員進(jìn)行繁重的內(nèi)存管理工作,而引用計(jì)數(shù)正式Python垃圾收集機(jī)制的一部分。

Python通過(guò)對(duì)一個(gè)對(duì)象的引用計(jì)數(shù)的管理來(lái)維護(hù)對(duì)象在內(nèi)存中的生存。我們知道在Python中每一個(gè)東西都是一個(gè)對(duì)象,都有一個(gè)ob_refcnt變量,正是這個(gè)變量維護(hù)著該對(duì)象的引用計(jì)數(shù),從而也最終決定著該對(duì)象的生生滅滅。

在Python中,主要是通過(guò)Py_INCREF(op)和Py_DECREF(op)兩個(gè)宏來(lái)增加和減少一個(gè)對(duì)象的引用計(jì)數(shù)。當(dāng)一個(gè)對(duì)象的引用計(jì)數(shù)減少到0之后,Py_DECREF將調(diào)用該對(duì)象的析構(gòu)函數(shù)(deallocator function)來(lái)釋放該對(duì)象所占有的內(nèi)存和系統(tǒng)資源。注意這里的析構(gòu)函數(shù)借用了C++的詞匯,實(shí)際上這個(gè)析構(gòu)動(dòng)作是通過(guò)在對(duì)象對(duì)應(yīng)的類型對(duì)象中定義的一個(gè)函數(shù)指針來(lái)刻畫的,還記得嗎?就是那個(gè)tp_dealloc。

如果熟悉設(shè)計(jì)模式中Observer模式,可以看到,這里隱隱約約透著Observer模式的影子。在ob_refcnt減為0之后,將觸發(fā)對(duì)象銷毀的事件;從Python的對(duì)象體系來(lái)看,各個(gè)對(duì)象又提供了不同的事件處理函數(shù),而事件的注冊(cè)動(dòng)作正是在各個(gè)對(duì)象對(duì)應(yīng)的類型對(duì)象中靜態(tài)完成的。

對(duì)于這兩個(gè)宏的參數(shù)op來(lái)說(shuō),不允許op是一個(gè)指向空對(duì)象的指針(NIL),如果op是一個(gè)NIL,那么必須使用Py_XINCREF/Py_XDECREF這一對(duì)宏。

在PyObject中我們看到ob_refcnt是一個(gè)32位的整形變量,這實(shí)際是一個(gè)Python所做的假設(shè),即對(duì)一個(gè)對(duì)象的引用不會(huì)超過(guò)一個(gè)整形變量的最大值。一般情況下,如果不是惡意代碼,這個(gè)假設(shè)顯然是不會(huì)被突破的。

需要注意的是,在Python的各種對(duì)象中,類型對(duì)象是超越引用計(jì)數(shù)規(guī)則的。類型對(duì)象“跳出三界外,不再五行中”,永遠(yuǎn)不會(huì)被析構(gòu)。每一個(gè)對(duì)象中指向類型對(duì)象的指針不被視為對(duì)類型對(duì)象的引用。

在每一個(gè)對(duì)象創(chuàng)建的時(shí)候,Python提供了一個(gè)_Py_NewReference(op)宏來(lái)將對(duì)象的引用計(jì)數(shù)初始化為1。

在Python的源代碼中可以看到,在不同的編譯選項(xiàng)下(Py_REF_DEBUG, Py_TRACE_REFS),引用計(jì)數(shù)的宏還要做許多額外的工作。下面展示的代碼是Python在最終發(fā)行時(shí)這些宏所對(duì)應(yīng)的實(shí)際的代碼:

  1. [object.h]   
  2. /* Without Py_TRACE_REFS, there's little enough to do that we expand code   
  3.  * inline.   
  4.  */   
  5. #define _Py_NewReference(op) ((op)->ob_refcnt = 1)   
  6. #define _Py_Dealloc(op) ((*(op)->ob_type->tp_dealloc)((PyObject *)(op)))   
  7. #define Py_INCREF(op) ((op)->ob_refcnt++)   
  8. #define Py_DECREF(op)                   \   
  9. if (--(op)->ob_refcnt != 0)         \   
  10.         ;            \   
  11. else                        \   
  12. _Py_Dealloc((PyObject *)(op))   
  13. /* Macros to use in case the object pointer may be NULL: */   
  14. #define Py_XINCREF(op) if ((op) == NULL) ; else Py_INCREF(op)   
  15. #define Py_XDECREF(op) if ((op) == NULL) ; else Py_DECREF(op)  

在一個(gè)對(duì)象的引用計(jì)數(shù)減為0時(shí),與該對(duì)象對(duì)應(yīng)的析構(gòu)函數(shù)就會(huì)被調(diào)用,但是要特別注意的是,調(diào)用析構(gòu)函數(shù)并不意味著最終一定會(huì)調(diào)用free釋放內(nèi)存空間,如果真是這樣的話,那頻繁地申請(qǐng)、釋放內(nèi)存空間會(huì)使Python的執(zhí)行效率大打折扣(更何況Python已經(jīng)多年背負(fù)了人們對(duì)其執(zhí)行效率的指責(zé):)。一般來(lái)說(shuō),Python中大量采用了內(nèi)存對(duì)象池的技術(shù),使用這種技術(shù)避免頻繁地申請(qǐng)和釋放內(nèi)存空間。因此在析構(gòu)時(shí),通常都是將對(duì)象占用的空間歸還到內(nèi)存池中。這一點(diǎn)在接下來(lái)對(duì)Python內(nèi)建對(duì)象的實(shí)現(xiàn)中可以看得一清二楚。

#p#

5、Python對(duì)象的分類

我們將Python的對(duì)象從概念上大致分為四類,需要指出的是,這種分類并不一定完全正確,不過(guò)是提供一種看待Python中對(duì)象的視角而已:

Math :數(shù)值對(duì)象

Container :容納其他對(duì)象的集合對(duì)象

Composition :表示程序結(jié)構(gòu)的對(duì)象

Internal :Python解釋器在運(yùn)行時(shí)內(nèi)部使用的對(duì)象

圖2列出了我們的對(duì)象分類體系,并給出了每一個(gè)類別中的一些實(shí)例:

詳解 Python 源碼之對(duì)象機(jī)制

6、通向Python之路

對(duì)Python源碼的剖析將分為四部分。

1.靜態(tài)對(duì)象剖析:首先我們會(huì)分析靜態(tài)的對(duì)象,Math對(duì)象和Container對(duì)象,深刻理解這些對(duì)象對(duì)我們理解Python解釋器的運(yùn)行會(huì)有很大的幫助,同時(shí),對(duì)我們編寫Python代碼也將大有裨益,在編寫Python代碼時(shí),你會(huì)清晰地意識(shí)到系統(tǒng)內(nèi)部這些對(duì)象將如何運(yùn)作,變化。當(dāng)然,我們并不會(huì)分析所有的Python對(duì)象,而是選取使用最頻繁的四種對(duì)象:PyIntObject, PyStringObject, PyListObject, PyDictObject進(jìn)行剖析。

2.運(yùn)行時(shí)剖析:在分析完靜態(tài)的對(duì)象之后,我們將進(jìn)入Python解釋器,在這里我們會(huì)詳細(xì)地考察Python的字節(jié)碼(byte code)以及解釋器對(duì)字節(jié)碼的解釋和執(zhí)行過(guò)程。這部分將完整地展現(xiàn)Python中所有的語(yǔ)法結(jié)構(gòu),如一般表達(dá)式,控制流,異常流,函數(shù),類等等的字節(jié)碼層面的實(shí)現(xiàn)細(xì)節(jié)。同時(shí),在這部分,我們會(huì)考察大部分的Python內(nèi)部對(duì)象。

3.編譯期剖析:這部分沒什么好打廣告的了,目標(biāo)明確,對(duì)象清晰,但是難度呢,絕不簡(jiǎn)單 :

4.運(yùn)行環(huán)境剖析:這部分將考察從激活PythonPython準(zhǔn)備就緒,可以接受用戶輸入或者執(zhí)行腳本文件,這段時(shí)間內(nèi),Python如何建立自己的運(yùn)行環(huán)境,并建立了怎樣的運(yùn)行環(huán)境,呵呵透露一下,想想Python那個(gè)龐大的builtin函數(shù)集合,這些就是這部分考察的重點(diǎn)。

閱讀完這些內(nèi)容之后,對(duì)于Python,你應(yīng)該是了如指掌了,在以后編寫Python代碼時(shí),你的腦子里甚至可以出現(xiàn)Python解釋器將如何一步步解釋你的代碼的情形。當(dāng)然,這只是我寫作本書的副產(chǎn)品。這本書誕生的真正原因只有一個(gè),興趣,我對(duì)Python的實(shí)現(xiàn)有濃厚的興趣。這本書也只是第一步,希望以后還能繼續(xù)對(duì)Python系列,如IronPython、Jython,PyPy的探索,當(dāng)然,對(duì)于其他動(dòng)態(tài)語(yǔ)言,比如Ruby的探索,我希望也會(huì)有時(shí)間去做。

小結(jié):詳解 Python 源碼之對(duì)象機(jī)制的內(nèi)容介紹完了,希望本文對(duì)你有幫助,更多關(guān)于Python 的內(nèi)容請(qǐng)參考編輯推薦。

責(zé)任編輯:zhaolei 來(lái)源: CSDN博客
相關(guān)推薦

2011-06-23 13:38:27

QT 元對(duì)象 信號(hào)

2011-06-23 14:05:32

Qt 事件機(jī)制

2021-09-01 06:48:16

AndroidGlide緩存

2021-08-17 13:41:11

AndroidView事件

2021-09-03 07:27:38

AndroidGlide管理

2021-12-30 22:50:32

KafkaConsumer 源碼

2021-09-09 06:55:43

AndroidViewDragHel原理

2011-08-18 10:59:57

iPhone開發(fā)消息通信NSNotificat

2011-06-23 14:40:13

Qt 信號(hào)

2009-07-08 13:22:30

JDK源碼分析Set

2011-08-23 13:56:12

MySQLConnection

2021-09-02 07:00:01

Glide流程Android

2022-05-14 22:27:40

Nacos訂閱機(jī)制定時(shí)器

2020-05-26 18:50:46

JVMAttachJava

2023-11-27 07:44:59

RabbitMQ機(jī)制

2023-06-15 14:09:00

解析器Servlet容器

2021-09-06 13:12:05

前端JavaScript編程

2021-09-07 06:40:25

AndroidLiveData原理

2022-04-06 14:55:45

Harmony同步機(jī)制鴻蒙

2021-09-12 07:30:10

配置
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)