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. 表示法

词法分析和语法的描述使用一种混合了 EBNFPEG 的文法表示法。例如:

name:   letter (letter | digit | "_")*
letter: "a"..."z" | "A"..."Z"
digit:  "0"..."9"

在此示例中,第一行表示一个 name 是一个 letter,后跟零个或多个 letterdigit 和下划线组成的序列。而一个 letter'a''z'AZ 之间的任意单个字符;一个 digit09 之间的任意单个字符。

每条规则都以一个名称(用于标识正在定义的规则)开头,后跟一个冒号 :。冒号右侧的定义使用以下语法元素:

  • name: 名称引用另一条规则。在可能的情况下,它会链接到该规则的定义。

    • TOKEN: 大写名称引用一个词法单元(token)。在文法定义中,词法单元与规则等同。

  • "text", 'text': 单引号或双引号中的文本必须逐字匹配(不包括引号)。引号的类型根据 text 的含义选择:

    • 'if': 单引号中的名称表示一个关键字

    • "case": 双引号中的名称表示一个软关键字

    • '@': 单引号中的非字母符号表示一个 OP 词法单元,即一个定界符操作符

  • 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.INDENTNEWLINE 等词法单元的空白字符。然后,*句法*定义使用这些词法单元,而不是源字符。

本文档对两种风格的定义使用相同的 BNF 文法。下一章(词法分析)中所有 BNF 的用法都是词法定义;后续章节中的用法则是句法定义。