# 5.2 Python 语言规范

CPython 源码中包含了 Python 语言的定义，其作为参考规范供所有 Python 解释器使用。

此规范使用了人机可读的文件格式。文档内是对 Python 语言的详细解释，概述了允许的内容以及每个语句的行为。

### 语言说明文档

`Doc/reference` 目录包含了 Python 语言特性的介绍。

此目录中有你要了解的整个语言、结构体和关键词的文件：

图片文字翻译：

compound\_stmts.rst：if、while、for 和函数定义等复合语句

datamodel.rst：对象、值和类型

executionmodel.rst：Python 程序的结构

expressions.rst：Python 表达式的元素

grammar.rst：Python 的核心语法（引用 `Grammar/Grammar`）

import.rst：import 系统

index.rst：语言参考索引

introduction.rst：参考文档介绍

lexical\_analysis.rst：词法结构，如行、缩进、单词符号和关键字

simple\_stmts.rst：assert、import、return 和 yield 等简单语句

toplevel\_components.rst：说明执行 Python 的方法，如脚本和模块

### 示例

在 `Doc/reference/compound_stmts.rst` 中，你可以看见一个定义 `with` 语句的简单例子。

`with` 语句有很多用法，最简单的用法是上下文管理的实例化和嵌套代码块：

```python
with x():
    ...
```

你可以使用 `as` 关键词将结果赋值给变量：

```python
with x() as y:
    ...
```

你还可以使用逗号将上下文管理器连接起来：

```python
with x() as y, z() as jk:
    ...
```

此文档包含了用户可读的语言规范，而机器可读的规范位于`Grammar/python.gram` 中。

### 语法文件

Python 语法文件使用解析表达式语法规范。在语法文件中，你可以使用如下符号：

* \* 用于零次或多次重复；
* \+ 用于一次或多次重复；
* \[] 用于可选部分；
* \| 用于可选择项；
* () 用于定义优先级。

举一个实例的例子来说明，如果让你定义一杯咖啡，你会怎么来定义：

* 它一定有一个杯子；
* 它必须包含一杯及以上的浓咖啡；
* 它可以有牛奶，但此项是可选择的；
* 它可以有水，但此项是可选择的；
* 如果它包含牛奶，那么牛奶可以是多种多样的，如：全脂牛奶，脱脂牛奶以及豆奶。

用 PEG 来定义一杯咖啡，一份咖啡订单看起来是这样的：

![](https://1029588898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJhewUmzI3BNeGgeFH9Rv%2Fuploads%2Fgit-blob-7e19a44536d89a1761febc6116ec0715331d3fca%2F%E5%9B%BE5.2.2%20%E7%94%A8EBNF%E5%AE%9A%E4%B9%89%E4%B8%80%E6%9D%AF%E5%92%96%E5%95%A1.png?alt=media)

{% hint style="info" %}
**参见**

CPython 3.9 的源代码有两个语法文件。一种传统语法是用一个被称为 BNF 范式的上下文无关文法所编写。 CPython 3.10 已经删除了 BNF 语法文件(Grammar/Grammar)。 BNF 不是 Python 语言特有的，许多其他语言也用 BNF 作为语法符号。
{% endhint %}

在本章节，你将使用铁路图来展示语法。下图是定义咖啡语句的铁路图。 ![](https://1029588898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJhewUmzI3BNeGgeFH9Rv%2Fuploads%2Fgit-blob-ccdcd79523a8259c8bd8daefa97233ed55399ed9%2F%E5%9B%BE5.2.3%20%E7%94%A8%E9%93%81%E8%B7%AF%E5%9B%BE%E6%9D%A5%E8%A1%A8%E7%A4%BA%E4%B8%80%E6%9D%AF%E5%92%96%E5%95%A1%E5%AE%9A%E4%B9%89%E8%BF%87%E7%A8%8B.png?alt=media)

在铁路图中，每个可能的组合都必须要从左到右排成一行。其中可选的语句可以被绕过，而一些语句可以形成循环。

![](https://1029588898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJhewUmzI3BNeGgeFH9Rv%2Fuploads%2Fgit-blob-5dbea11ee3b0716f5dd45ddee3b54ab2538f6075%2F%E5%9B%BE5.2.4%20with%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%9A%84%E5%AE%9A%E4%B9%89.png?alt=media)

## 一个例子：while 语句

`while` 语句有多种形式。最简单的形式包含了一个表达式，然后是一个 : 终结符号以及一个代码块：

```
while finished == True:
    do_things()
```

或者，你可以使用一个赋值表达式，它在语法中被称为 `named_expression`。这是 Python 3.8 的新增特性：

```
while letters := read(document, 10):
    print(letters)
```

此外，`while` 语句后面还可以跟一个 `else` 语句和代码块。

```
while item := next(iterable):
    print(item)
    else:
        print("Iterable is empty")
```

如果你在语法文件中搜索 `while_stmt`，则会看到如下定义：

```
while_stmt[stmt_ty]:
| 'while' a=named_expression ':' b=block c=[else_block] ...
```

引号中的任何内容都是字符串文字，被称为**终结符号**。 终结符号用于识别关键字。

这两行定义还引用了另外两个定义：

1. **block** 是指包含一个及以上语句的代码块；
2. **named\_expression** 指的是一个简单表达式或者一个赋值表达式。

用铁路图来展示，`while` 语句如下所示：

图片不翻译

作为一个更加复杂的案例，`try` 语句在语法中的定义如下所示：

图片不翻译

`try` 语句有有两种用法：

1. `try` 只有一个 `finally` 语句；
2. `try` 有一个或多个 `except` 从句，后面跟一个可选的 `else` , 然后是一个可选的 `finally`。

用铁路图来展示，如下图所示：

图片不翻译

`try` 语句是一个更加复杂的优秀示例。

如果你想详细了解 Python 语言，那就通读定义在 `Grammar/python.gram` 中的语法。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hai-shi.gitbook.io/cpython-internals/5-language-and-grammar/5.2-python-language-specification.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
