
Python 是直譯語言其實你每天都在編譯它結語在拿 Python 和其它語言做比較時我們常聽到「C、C 是「編譯式語言compiled languagePython 則是直譯式語言interpreted language。」彷彿 Python 就是直譯器打開原始碼一行一行邊讀邊執行中間根本沒有「編譯」這道手續。但其實在 Python 官方 Glossary 文件中的interpreted詞條中都不敢把話說死“Python is an interpreted language, as opposed to a compiled one, thoughthe distinction can be blurry because of the presence of the bytecode compiler.”官方一方面說 Python 是直譯語言另一方面卻又說因為存在一個bytecode 編譯器所以這條「直譯 vs. 編譯」的界線其實是模糊的。也就是說「Python 是純直譯語言」這個說法並不精確。那麼Python 究竟是如何同時牽涉到「編譯」與「直譯」的呢官方 Glossary 的bytecode詞條給了最直接的答案——它用一句話就把這兩道流程都講清楚了“Python source code iscompiled into bytecode, the internal representation of a Python program in the CPython interpreter. … This ‘intermediate language’ is said torun on a virtual machinethat executes the machine code corresponding to each bytecode.”前半句說了編譯階段是將 source code 轉換成 bytecode後半句則說直譯階段是在虛擬機virtual machine上執行 byteode也就是說實際執行python script.py時原始碼並非「直接被一行一行直譯」而是會先被編譯compile成bytecode位元組碼code object再交給直譯器CPython VM逐條執行interpret。bytecode 橫跨編譯與直譯兩端的這個特性在標準函式庫的dis模組文件裡也看得到。這個模組專門用來反組譯disassemblePython 的 bytecode它的說明在描述 CPython bytecode 時更是把「編譯」與「直譯」兩端寫進了同一句話“The CPython bytecode … is …used by the compiler and the interpreter.”這段話中同時出現 compiler 與 interpreter可以作為編譯與直譯這兩道流程都同時存在的強力佐證結語回到最初那句「Python 是直譯式語言」——現在我們可以說得更精確Python 不單是直譯式語言它同時也經過編譯這道手續。這一點並非只有官方文件這樣說。Eddie Antonio Santos 在 Python is a compiled language 一文中用了一個很有意思的手法佐證相同的結論他刻意在原始碼裡埋下多個錯誤藉此觀察 Python 到底是怎麼跑的——結果這些錯誤並不是照著它們在程式碼裡的順序一個一個被檢出報錯的。這證明了 Python 至少不是我們一開始想像的那種「打開原始碼、一行一行邊讀邊執行」的純直譯式語言。至於他是怎麼一步步設計實驗、推導出這個結論的就留待有興趣的讀者自行參閱原文一探究竟。那麼這道一路被我們提及、卻還沒真正拆開來看的「編譯」手續內部到底經歷了哪些步驟根據 Compiler design 這篇文章Python 的編譯流程會依序經過 tokenize → parse → AST → control flow graph → bytecode一路將 source code 轉換成 bytecode而到了執行階段則交由Python/ceval.c裡的求值迴圈evaluation loop逐條執行。至於每一步的細節就留待下一篇深入查看。