1. 引言¶
本參考手冊描述了 Python 程式語言。它並非用作教程。
雖然我力求精確,但除了語法和詞法分析之外,我選擇使用英語而非形式化規約來描述所有內容。這應該能讓普通讀者更容易理解該文件,但也會留下模糊不清的餘地。因此,假如你來自火星,並試圖僅根據這份文件來重新實現 Python,你可能需要靠猜測,而實際上你最終實現的可能會是相當不同的語言。另一方面,如果你正在使用 Python,並且想知道該語言某個特定方面的精確規則,你絕對可以在這裡找到它們。如果你想看到對該語言更形式化的定義,或許你可以自願貢獻你的時間——或者發明一臺克隆機 :-)。
在語言參考文件中加入過多的實現細節是危險的——實現可能會改變,而同一語言的其他實現方式也可能不同。另一方面,CPython 是目前廣泛使用的 Python 實現(儘管其他替代實現的支援度也在不斷增加),其特有的怪癖有時也值得一提,特別是當該實現施加了額外限制時。因此,你會在文中發現散佈著簡短的“實現說明”。
每個 Python 實現都附帶了許多內建模組和標準模組。這些模組的文件記錄在《Python 標準庫》中。當一些內建模組與語言定義有重要互動時,本文會提及它們。
1.1. 其他實現¶
儘管有一個 Python 實現迄今為止最為流行,但還有一些替代實現對於不同受眾具有特別的吸引力。
已知的實現包括:
- CPython
這是 Python 的原始實現,也是維護最積極的實現,用 C 語言編寫。新的語言特性通常會最先在這裡出現。
- Jython
用 Java 實現的 Python。此實現可作為 Java 應用程式的指令碼語言,或用於建立使用 Java 類庫的應用程式。它也常用於為 Java 庫建立測試。更多資訊可以在 Jython 網站上找到。
- Python for .NET
該實現實際上使用了 CPython 實現,但它是一個託管的 .NET 應用程式,並提供了 .NET 庫的訪問。它由 Brian Lloyd 建立。更多資訊請參閱 Python for .NET 主頁。
- IronPython
另一個 Python for .NET 的實現。與 Python.NET 不同,這是一個完整的 Python 實現,可以生成 IL,並將 Python 程式碼直接編譯成 .NET 程式集。它由 Jython 的最初建立者 Jim Hugunin 建立。更多資訊請參閱 IronPython 網站。
- PyPy
一個完全用 Python 編寫的 Python 實現。它支援一些在其他實現中找不到的高階特性,如無棧(stackless)支援和即時(Just in Time)編譯器。該專案的目標之一是透過讓修改直譯器變得更容易(因為它是由 Python 編寫的)來鼓勵對語言本身的實驗。更多資訊可在 PyPy 專案主頁上獲得。
這些實現中的每一個都在某些方面與本手冊中記錄的語言有所不同,或者引入了標準 Python 文件未涵蓋的特定資訊。請參考特定實現的文件,以確定你需要了解的關於你所使用的具體實現的更多資訊。
1.2. 表示法¶
詞法分析和語法的描述使用一種混合了 EBNF 和 PEG 的文法表示法。例如:
name:letter
(letter
|digit
| "_")* letter: "a"..."z" | "A"..."Z" digit: "0"..."9"
在此示例中,第一行表示一個 name
是一個 letter
,後跟零個或多個 letter
、digit
和下劃線組成的序列。而一個 letter
是 'a'
到 'z'
和 A
到 Z
之間的任意單個字元;一個 digit
是 0
到 9
之間的任意單個字元。
每條規則都以一個名稱(用於標識正在定義的規則)開頭,後跟一個冒號 :
。冒號右側的定義使用以下語法元素:
name
: 名稱引用另一條規則。在可能的情況下,它會連結到該規則的定義。TOKEN
: 大寫名稱引用一個詞法單元(token)。在文法定義中,詞法單元與規則等同。
"text"
,'text'
: 單引號或雙引號中的文字必須逐字匹配(不包括引號)。引號的型別根據text
的含義選擇:e1 e2
: 僅由空格分隔的項表示一個序列。這裡,e1
必須後跟e2
。e1 | e2
: 豎線用於分隔備選項。它表示 PEG 的“有序選擇”:如果e1
匹配,則不再考慮e2
。在傳統的 PEG 文法中,這通常寫作斜槓/
,而不是豎線。更多背景和細節請參見 PEP 617。e*
: 星號表示前一項重複零次或多次。e+
: 同樣,加號表示重複一次或多次。[e]
: 方括號內的短語表示出現零次或一次。換句話說,括號內的短語是可選的。e?
: 問號與方括號的含義完全相同:前一項是可選的。(e)
: 圓括號用於分組。
以下表示法僅用於詞法定義。
"a"..."z"
: 由三個點分隔的兩個字面字元表示在給定的 ASCII 字元範圍(含兩端)內任選一個字元。<...>
: 尖括號內的短語給出了對匹配符號的非正式描述(例如,<any ASCII character except "\">
),或在附近文字中定義的縮寫(例如,<Lu>
)。
一些定義還使用*先行斷言*(lookaheads),它表示一個元素必須(或必須不)在給定位置匹配,但不會消耗任何輸入:
&e
: 肯定先行斷言(即,要求e
必須匹配)!e
: 否定先行斷言(即,要求e
*不*匹配)
一元運算子(*
、+
、?
)的繫結優先順序最高;豎線(|
)的繫結優先順序最低。
空白字元僅用於分隔詞法單元。
規則通常包含在一行內,但過長的規則可能會換行:
literal: stringliteral | bytesliteral | integer | floatnumber | imagnumber
或者,規則也可以格式化為第一行在冒號處結束,每個備選項以豎線開頭並另起一行。例如:
literal: | stringliteral | bytesliteral | integer | floatnumber | imagnumber
這並*不*意味著存在一個空的第一個備選項。
1.2.1. 詞法和句法定義¶
*詞法*分析和*句法*分析之間存在一些差異:詞法分析器處理輸入源的單個字元,而*解析器*(句法分析器)則處理詞法分析生成的詞法單元流。然而,在某些情況下,這兩個階段之間的確切界限是 CPython 的實現細節。
兩者之間的實際區別在於,在*詞法*定義中,所有空白字元都是有意義的。詞法分析器會丟棄所有未被轉換為 token.INDENT
或 NEWLINE
等詞法單元的空白字元。然後,*句法*定義使用這些詞法單元,而不是源字元。
本文件對兩種風格的定義使用相同的 BNF 文法。下一章(詞法分析)中所有 BNF 的用法都是詞法定義;後續章節中的用法則是句法定義。