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 的用法都是词法定义;后续章节中的用法则是句法定义。