編輯推薦
本書的主要特點:一本深入剖析Python具體實現的著作
內容新鮮,採用最新的Python語言版本(25)
大量的圖表形象地展示Python內部的運作機理
在原理介紹的同時,帶領讀者一起動手對Python虛擬機進行改造
完整覆蓋Python所有的核心議題,深刻揭示Python與C/C++之間如何互動
內容簡介
為了更好地利用Python語言,無論是使用Python語言本身,還是將Python與C/C++互動使用,深刻理解Python的運行原理都是非常重要的。本書以CPython為研究對象,在C代碼一級,深入細緻地剖析了Python的實現。書中不僅包括了對大量Python內置對象的剖析,更將大量的篇幅用於對Python虛擬機及Python高級特性的剖析。通過此書,讀者能夠透徹地理解Python中的一般表達式、控制結構、異常機制、類機制、多執行緒機制、模組的動態載入機制、記憶體管理機制等核心技術的運行原理,同時,本書所揭示的動態語言的核心技術對於理解其他動態語言,如Javascript、Ruby等也有較大的參考價值。
本書適合於Python程式設計師、動態語言愛好者、C程式設計師閱讀。
作者簡介
陳儒,計算機科學與工程專業碩士,問天(北京)信息技術有限公司技術負責人,致力於信息檢索方向的研究與開發。
圖書目錄
第0章 PYTHON源碼剖析--編譯PYTHON
0.1 PYTHON總體架構
0.2 PYTHON原始碼的組織
0.3 WINDOWS環境下編譯PYTHON
0.4 UNIX/LINUX環境下編譯PYTHON
0.5 修改PYTHON原始碼
0.6 通往PYTHON之路
0.7 一些注意事項
第1部分 PYTHON內建對象
第1章 PYTHON對象初探
1.1 PYTHON內的對象
1.1.1 對象機制的基石——PyObject
1.1.2 定長對象和變長對象
1.2 類型對象
1.2.1 對象的創建
1.2.2 對象的行為
1.2.3 類型的類型
1.3 PYTHON對象的多態性
1.4引用計數
1.5 PYTHON對象的分類
第2章 PYTHON中的整數對象
2.1 初識PYINTOBJECT對象
2.2 PYINTOBJECT對象的創建和維護
2.2.1 對象創建的3種途徑
2.2.2 小整數對象
2.2.3 大整數對象
2.2.4 添加和刪除
2.2.5 小整數對象池的初始化
2.3 HACK PYINTOBJECT
第3章 PYTHON中的字元串對象
3.1 PYSTRINGOBJECT與PYSTRING_TYPE
3.2 創建PYSTRINGOBJECT對象
3.3 字元串對象的INTERN機制
3.4 字元緩衝池
3.5 PYSTRINGOBJECT效率相關問題
3.6 HACK PYSTRINGOBJECT
第4章 PYTHON中的LIST對象
4.1 PYLISTOBJECT對象
4.2 PYLISTOBJECT對象的創建與維護
4.2.1 創建對象
4.2.2 設定元素
4.2.3 插入元素
4.2.4 刪除元素
4.3 PYLISTOBJECT對象緩衝池
4.4 HACK PYLISTOBJECT
第5章 PYTHON中的DICT對象
5.1 散列表概述
5.2 PYDICTOBJECT
5.2.1 關聯容器的entry
5.2.2 關聯容器的實現
5.3 PYDICTOBJECT的創建和維護
5.3.1 PyDictObject對象創建
5.3.2 PyDictObject中的元素搜尋
5.3.3 插入與刪除
5.3.4 操作示例
5.4 PYDICTOBJECT對象緩衝池
5.5 HACK PYDICTOBJECT
第6章 最簡單的PYTHON模擬——SMALL PYTHON
6.1 SMALL PYTHON
6.2 對象機制
6.3 解釋過程
6.4 互動式環境
第2部分 PYTHON虛擬機
第7章 PYTHON的編譯結果--CODE對象與PYC檔案
7.1 PYTHON程式的執行過程
7.2 PYTHON編譯器的編譯結果--PYCODEOBJECT對象
7.2.1 PyCodeObject對象與pyc檔案
7.2.2 Python源碼中的PyCodeObject
7.2.3 pyc檔案
7.2.4 在Python中訪問PyCodeObject對象
7.3 PYC檔案的生成
7.3.1 創建pyc檔案的具體過程
7.3.2 向pyc檔案寫入字元串
7.3.3 一個PyCodeObject,多個PyCodeObject
7.4 PYTHON的位元組碼
7.5 解析PYC檔案
第8章 PYTHON虛擬機框架
8.1 PYTHON虛擬機中的執行環境
8.1.1 Python源碼中的PyFrameObject
8.1.2 PyFrameObject中的動態記憶體空間
8.1.3 在Python中訪問PyFrameObject對象
8.2 名字、作用域和名字空間
8.2.1 Python程式的基礎結構——module
8.2.2 約束與名字空間
8.2.3 作用域與名字空間
8.3 PYTHON虛擬機的運行框架
8.4 PYTHON運行時環境初探
第9章 PYTHON虛擬機中的一般表達式
9.1 簡單內建對象的創建
9.2 複雜內建對象的創建
9.3 其他一般表達式
9.3.1 符號搜尋
9.3.2 數值運算
9.3.3 信息輸出
第10章 PYTHON虛擬機中的控制流
10.1 PYTHON虛擬機中的IF控制流
10.1.1 研究對象--if_control.py
10.1.2 比較操作
10.1.3 指令跳躍
10.2 PYTHON虛擬機中的FOR循環控制流
10.2.1 研究對象——for_control.py
10.2.2 循環控制結構的初始化
10.2.3 疊代控制
10.2.4 終止疊代
10.3 PYTHON虛擬機中的WHILE循環控制結構
10.3.1 研究對象——while_control.py
10.3.2 循環終止
10.3.3 循環的正常運轉
10.3.4 循環流程改變指令之continue
10.3.5 循環流程改變指令之break
10.4 PYTHON虛擬機中的異常控制流
10.4.1 Python中的異常機制
10.4.2 Python中的異常控制語義結構
第11章 PYTHON虛擬機中的函式機制
11.1 PYFUNCTIONOBJECT對象
11.2 無參函式調用
11.2.1函式對象的創建
11.2.2 函式調用
11.3 函式執行時的名字空間
11.4 函式參數的實現
11.4.1 參數類別
11.4.2 位置參數的傳遞
11.4.3 位置參數的訪問
11.4.4 位置參數的默認值
11.4.5 擴展位置參數和擴展鍵參數
11.5 函式中局部變數的訪問
11.6.1 實現閉包的基石
11.6.2 閉包的實現
11.6.3 Decorator
第12章 PYTHON虛擬機中的類機制
12.1 PYTHON中的對象模型
12.1.1 對象間的關係
12.1.2 和
12.2 從TYPE對象到CLASS對象
12.2.1 處理基類和type信息
12.2.2 處理基類列表
12.2.3 填充tp_dict
12.3 用戶自定義CLASS
12.3.1 創建class對象
12.4 從CLASS對象到INSTANCE對象
12.5 訪問INSTANCE對象中的屬性
12.5.1 instance對象中的__dict__
12.5.2 再論descriptor
12.5.3 函式變身
12.5.4 無參函式的調用
12.5.5 帶參函式的調用
12.5.6 Bound Method和unboundMethod
12.6 千變萬化的DESCRIPTOR
第3部分 PYTHON高級話題
第13章 PYTHON運行環境初始化
13.1 執行緒環境初始化
13.1.1 執行緒模型回顧
13.1.2 初始化執行緒環境
13.2 系統MODULE初始化
13.2.1 創建__builtin__ module
13.2.2 創建sys module
13.2.3 創建__main__ module
13.2.4 設定site-specific的module的搜尋路徑
13.3 激活PYTHON虛擬機
13.3.1 互動式運行方式
13.3.2 腳本檔案運行方式
13.3.3 啟動虛擬機
13.3.4 名字空間
第14章 PYTHON模組的動態載入機制
14.1 IMPORT前奏曲
14.2 PYTHON中IMPORT機制的黑盒探測
14.2.1 標準import
14.2.2 嵌套import
14.2.3 import package
14.2.4 from與import
14.2.5 符號重命名
14.2.6 符號的銷毀與重載
14.3 IMPORT機制的實現
14.3.1 解析module/package樹狀結構
14.3.2 載入module/pakcage
14.3.3 from與import
14.4 PYTHON中的IMPORT操作
14.4.1 import module
14.4.2 import package
14.4.3 from & import
14.4.4 import & as
14.4.5 reload
14.4.6 內建module:imp
14.5 與MODULE有關的名字空間問題
第15章 PYTHON多執行緒機制
15.1 GIL與執行緒調度
15.2 初見PYTHON THREAD
15.3 PYTHON執行緒的創建
15.3.1 建立多執行緒環境
15.3.2 創建執行緒
15.4 PYTHON執行緒的調度
15.4.1 標準調度
15.4.2 阻塞調度
15.5 PYTHON子執行緒的銷毀
15.6 PYTHON執行緒的用戶級互斥與同步
15.6.1 用戶級互斥與同步
15.6.2 Lock對象
15.7 高級執行緒庫——THREADING
15.7.1 Threading Module概述
15.7.2 Threading的執行緒同步工具
15.7.3 Threading中的Thread
第16章 PYTHON的記憶體管理機制
16.1 記憶體管理架構
16.2 小塊空間的記憶體池
16.2.1 Block
16.2.2 Pool
16.2.3 arena
16.2.4 記憶體池
16.3 循環引用的垃圾收集
16.3.1 引用計數與垃圾收集
16.3.2 三色標記模型
16.4 PYTHON中的垃圾收集
16.4.1 可收集對象鍊表
16.4.2 分代的垃圾收集
16.4.3 Python中的標記-清除方法
16.4.4 垃圾收集全景
16.4.5 Python中的gc模組
16.4.6 總結
書摘插圖
第1章 Python對象初探
對象是Python中最核心的一個概念,在Python的世界中,一切都是對象,一個整數是一個對象,一個字元串也是一個對象。更為奇妙的是,類型也是一種對象,整數類型是一個對象,字元串類型也是一個對象。換句話說,面向對象理論中的“類”和“對象”這兩個概念在Python中都是通過Python內的對象來實現的。
在Python中,已經預先定義了一些類型對象,比如int類型、string類型、dict類型等,這些我們稱之為內建類型對象。這些類型對象實現了面向對象中“類”的概念;這些內建類型對象通過“實例化”,可以創建內建類型對象的實例對象,比如int對象、string對象、dict對象。類似的,這些實例對象可以視為面向對象理論中“對象”這個概念在Python中的體現。
同時,Python還允許程式設計師通過class A(object)這樣的表達式自己定義類型對象。基於這些類型對象,同樣可以進行“實例化”的操作,創建的對象稱為“實例對象”。Python中不光有著這些千差萬別的對象,這些對象之間還存在著各種複雜的關係,從而構成了我們稱之為“類型系統”或“對象體系”的東西。
Python中的對象體系是一個龐大而複雜的體系,如果說在本書的第一章我就試圖將這個體系闡釋清楚,這只能說明我是個瘋子。在本章中,我們的重點將放在了解對象在Python內部是如何表示的,更確切地說,因為Python是由C實現的,所以我們首先要弄清楚的一個問題就是:對象,這個神奇的東西,在C的層面,究竟長得是個什麼模樣,究竟是三頭六臂,還是烈焰紅唇。
除此之外,我們還將了解到類型對象在C的層面是如何實現的,並初步認識類型對象的作用及它與實例對象的關係。總之,本章對Python對象體系的介紹力求簡潔,但是並不膚淺,有的地方甚至會相當深入。因此,在本章的閱讀中,如果有什麼疑難的地方,沒有關係,先放下,只要有一個直觀的感覺就可以了,這並不妨礙你閱讀接下來的內容。
本章的目的是為能夠順利而快速地進入對內建對象的剖析打下必要的基礎,至於對Python對象體系的詳細剖析,會在第2部分的最後一章中介紹到。只有到了那個時候,我們才有足夠的能力將這個體系看個明白。
1.1 Python內的對象
從1989年Guido在聖誕節揭開Python的大幕開始,一直到現在,Python經歷了一次一次的升級,但是其實現語言一直都是ANSI C。我們知道,C並不是一個面向對象的語言,那么在Python中,它的對象機制是如何實現的呢?
對於人的思維來說,對象是一個比較形象的概念,而對於計算機來說,對象卻是一個抽象的概念。它並不能理解這是一個整數,那是一個字元串,對於計算機來說,它所知道的一切都是位元組。通常的說法是,對象是數據以及基於這些數據的操作的集合。在計算機中,一個對象實際上就是一片被分配的記憶體空間,這些記憶體可能是連續的,也可能是離散的,這都不重要,重要的是這片記憶體在更高的層次上可以作為一個整體來考慮,這個整體就是一個對象。在這片記憶體中,存儲著一系列的數據以及可以對這些數據進行修改或讀取操作的一系列代碼。
在Python中,對象就是為C中的結構體在堆上申請的一塊記憶體,一般來說,對象是不能被靜態初始化的,並且也不能在棧空間上生存。唯一的例外就是類型對象,Python中所有的內建的類型對象(如整數類型對象,字元串類型對象)都是被靜態初始化的。
在Python中,一個對象一旦被創建,它在記憶體中的大小就是不變的了。這就意味著那些需要容納可變長度數據的對象只能在對象內維護一個指向一塊可變大小的記憶體區域的指針。為什麼要設定這樣一條特殊的規則呢,因為遵循這樣的規則可以使通過指針維護對象的工作變得非常的簡單。一旦允許對象的大小可在運行期改變,我們就可以考慮如下的情形。在記憶體中有對象A,並且其後緊跟著對象B。如果運行期某個時刻,A的大小增大了,這意味著必須將A整個移動到記憶體中的其他位置,否則A增大的部分將覆蓋原本屬於B的數據。只要將A移動到記憶體中的其他位置,那么所有指向A的指針就必須立即得到更新,光是想一想,就知道這樣的工作是多么的繁瑣。
……