0% found this document useful (0 votes)
32 views65 pages

00 Python

这篇文档介绍了Python的基础知识,包括安装Python、常用命令、词法分析、数据模型等内容。文档内容详细,从Python的基本使用到内部实现原理提供了系统的介绍。

Uploaded by

dongyeoh1985
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
32 views65 pages

00 Python

这篇文档介绍了Python的基础知识,包括安装Python、常用命令、词法分析、数据模型等内容。文档内容详细,从Python的基本使用到内部实现原理提供了系统的介绍。

Uploaded by

dongyeoh1985
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 65

# 自定义模块

# Python 基础

## 安装 Python

从官网下载最新版的 python 安装包

## 常用命令

```python
python [-bBdEhiIOqsSuvVWx?] [-c command | -m module-name | script | - ] [args]
```

### 查看版本

```
python --version
```

### 查看模块信息

```
pip show [模块名称]
```

## USER_BASE 与 USER_SITE

<p><code>user_site</code>是 Python 中的一个变量,用于指定用户自定义的包安装路径。当我们在使用


<code>pip</code>或<code>setup.py</code>安装一个 Python 包时,包会默认安装到系统的全局目录中,
一般情况下需要管理员权限才能安装。而<code>user_site</code>提供了一个可以让用户自定义包安装路径
的选项。</p>

<p>与<code>user_site</code>类似,<code>user_base</code>也是一个变量,用于指定用户自定义的
包安装路径。不同的是,<code>user_base</code>不仅可以用来安装 Python 包,还可以安装 Python 二进
制文件和其他可执行文件。</p>

通过修改环境变量`PYTHONUSERBASE`可以设置他们的值

## 词法分析

- 逻辑行

- 物理行

- 注释

#开头

- 编码声明

```python
# -*- coding: <encoding-name> -*-
```

- 显式拼接物理行为逻辑行,使用反斜杠 \

```python
if 1900 < year < 2100 and 1 <= month <= 12 \
and 1 <= day <= 31 and 0 <= hour < 24 \
and 0 <= minute < 60 and 0 <= second < 60: # Looks like a valid date
return 1
```

- 隐式拼接

圆括号、方括号、花括号内的表达式可以分成多个物理行,不必使用反斜杠

```python
month_names = ['Januari', 'Februari', 'Maart', # These are the
'April', 'Mei', 'Juni', # Dutch names
'Juli', 'Augustus', 'September', # for the months
'Oktober', 'November', 'December'] # of the year
```

- 空白行 :空格符、制表符(8 个空格)、换页符、注释的逻辑行

- 缩进:逻辑行开头的空白符(空格符和制表符)用于计算该行的缩进层级,决定语句组块;缩进层级以堆栈形
式生成 INDENT 和 DEDENT 形符

- 标识符:大小写字母 `A` 至 `Z`、下划线 `_` 、数字 `0` 至 `9`,但不能以数字开头;标识符的长度没


有限制,但区分大小写

- 关键字

```python
False await else import pass
None break except in raise
True class finally is return
and continue for lambda try
as def from nonlocal while
assert del global not with
async elif if or yield
```

- 软关键字:某些标识符仅在特定上下文中被保留,如:`match`, `case` 和 `_` 等

- 保留的标识符类

_*:不会被 `from module import *` 所导入

_:在 [`match`]语句内部的 `case` 模式中,`_` 是一个 [软关键字],它表示 [通配符]

\_\_*\_\_:系统定义的名称,这些名称由解释器及其实现(包括标准库)定义

__*:类的私有名称

- 字符串及字节串字面值
```python
stringliteral ::= [stringprefix](shortstring | longstring)
stringprefix ::= "r" | "u" | "R" | "U" | "f" | "F"
| "fr" | "Fr" | "fR" | "FR" | "rf" | "rF" | "Rf" | "RF"
shortstring ::= "'" shortstringitem* "'" | '"' shortstringitem* '"'
longstring ::= "'''" longstringitem* "'''" | '"""' longstringitem* '"""'
shortstringitem ::= shortstringchar | stringescapeseq
longstringitem ::= longstringchar | stringescapeseq
shortstringchar ::= <any source character except "\" or newline or the quote>
longstringchar ::= <any source character except "\">
stringescapeseq ::= "\" <any source character>
```

```python
bytesliteral ::= bytesprefix(shortbytes | longbytes)
bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" |
"RB"
shortbytes ::= "'" shortbytesitem* "'" | '"' shortbytesitem* '"'
longbytes ::= "'''" longbytesitem* "'''" | '"""' longbytesitem* '"""'
shortbytesitem ::= shortbyteschar | bytesescapeseq
longbytesitem ::= longbyteschar | bytesescapeseq
shortbyteschar ::= <any ASCII character except "\" or newline or the quote>
longbyteschar ::= <any ASCII character except "\">
bytesescapeseq ::= "\" <any ASCII character>
```

| 转义序列 | 含意 | 备注 |
| :----------- | :---------------------- | :------------------- |
| `\`<newline> | 忽略反斜杠与换行符 | 拼接字符串 |
| `\\` | 反斜杠(`\`) | |
| `\'` | 单引号(`'`) | |
| `\"` | 双引号(`"`) | |
| `\a` | ASCII 响铃(BEL) | |
| `\b` | ASCII 退格符(BS) | |
| `\f` | ASCII 换页符(FF) | |
| `\n` | ASCII 换行符(LF) | |
| `\r` | ASCII 回车符(CR) | |
| `\t` | ASCII 水平制表符(TAB) | |
| `\v` | ASCII 垂直制表符(VT) | |
| `\ooo` | 八进制数 *ooo* 字符 | 最多接受 3 个 8 进制数字 |
| `\xhh` | 十六进制数 *hh* 字符 | 必须为 2 个 16 进制字母 |

- 字符串字面值合并:以空白符分隔的多个相邻字符串或字节串字面值,可用不同引号(',",''',""")标注,
等同于合并操作

- 字符串字面值格式化:

```python
f_string ::= (literal_char | "{{" | "}}" | replacement_field)*
replacement_field ::= "{" f_expression ["="] ["!" conversion] [":" format_spec]
"}"
f_expression ::= (conditional_expression | "*" or_expr)
("," conditional_expression | "," "*" or_expr)* [","]
| yield_expression
conversion ::= "s" | "r" | "a"
format_spec ::= (literal_char | NULL | replacement_field)*
literal_char ::= <any code point except "{", "}" or NULL>
```

- 字符串格式化规范 [详
见](https://docs.python.org/zh-cn/3/library/string.html#formatspec)

```python
format_spec ::= [[fill]align][sign]["z"]["#"]["0"][width][grouping_option]
["." precision][type]
fill ::= <any character>
align ::= "<" | ">" | "=" | "^"
sign ::= "+" | "-" | " "
width ::= digit+
grouping_option ::= "_" | ","
precision ::= digit+
type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" |
"o" | "s" | "x" | "X" | "%"
```

- 整数字面值

```python
integer ::= decinteger | bininteger | octinteger | hexinteger
decinteger ::= nonzerodigit (["_"] digit)* | "0"+ (["_"] "0")*
bininteger ::= "0" ("b" | "B") (["_"] bindigit)+
octinteger ::= "0" ("o" | "O") (["_"] octdigit)+
hexinteger ::= "0" ("x" | "X") (["_"] hexdigit)+
nonzerodigit ::= "1"..."9"
digit ::= "0"..."9"
bindigit ::= "0" | "1"
octdigit ::= "0"..."7"
hexdigit ::= digit | "a"..."f" | "A"..."F"
```

下划线(_):没有实际意义;下划线只是为了分组数字,让数字更易读

- 浮点数字面值

```python
floatnumber ::= pointfloat | exponentfloat
pointfloat ::= [digitpart] fraction | digitpart "."
exponentfloat ::= (digitpart | pointfloat) exponent
digitpart ::= digit (["_"] digit)*
fraction ::= "." digitpart
exponent ::= ("e" | "E") ["+" | "-"] digitpart
```

- 虚数字面值

```python
imagnumber ::= (floatnumber | digitpart) ("j" | "J")
```

- 运算符
```python
+ - * ** / // % @
<< >> & | ^ ~ :=
< > <= >= == !=
```

- 分隔符

```python
( ) [ ] { }
, : . ; @ = ->
+= -= *= /= //= %= @=
&= |= ^= >>= <<= **=
```

- 特殊含义

```python
' " # \
```

- 字符串字面值及注释外不能出现的字符

```python
$ ? `
```

## 数据模型

### 对象、值和类型

- 对象及对象间关系,标识符,类型及值,类型决定对象可以有的属性

id(x):对象的标识符或地址,标识符不可改变

x.is(y):x,y 的标识符是否一致

type(x):x 的类型,类型不可改变

可变对象:值可以改变,如:字典和列表

不可变对象:值不可以改变,如:数字,字符串和元组

对象绝不会显式销毁

使用 try...finally 或 with 保证外部对象调用 close 方法进行释放

### 标准类型层级结构

以下是 Python 内置类型的列表。扩展模块 (具体实现会以 C, Java 或其他语言编写) 可以定义更多的类型

- None:空值,逻辑为假,无返回值函数返回 None
- NotImplemented:未实现指定运算时返回

- Ellipsis:...

- numbers.Number:数字,整数(整型和布尔型)numbers.Integral,浮点数(双精
度)numbers.Real,和复数 numbers.Complex

- 序列:此类对象表示以非负整数作为索引的有限有序集

不可变序列:字符串、元组、字节串

可变序列:列表,字节数组

- 集合:此类对象表示由不重复且不可变对象组成的无序且有限的集合

- 映射:就是字典,此类对象表示由任意索引集合所索引的对象的集合,通过下标 `a[k]` 可在映射 `a` 中选


择索引为 `k` 的条目

- 可调用类型:

用户定义函数:def

实例方法:

生成器函数:yield,用于迭代逐个获取

协程函数:async def

异步生成器函数:async def+yield

内置函数:C 函数的外部封装

内置方法:同【内置函数】

类:\_\_new\_\_

类实例:\_\_call\_\_

- 模块:模块是 Python 代码的基本组织单元

导入方式:import、importlib.import_module() 、\_\_import\_\_()

模块对象具有由字典对象实现的命名空间(这是被模块中定义的函数的 `__globals__` 属性引用的字典)

属性:\_\_name\_\_,\_\_doc\_\_,\_\_file\_\_,\_\_dict\_\_

- 自定义类:class

- 类实例:类实例可通过调用类对象来创建

- I/O 对象 :file object


打开方式:open(),os.popen,os.fdopen,makefile

sys.stdin,sys.stdout,sys.stderr 对应于解释器标准输入、输出和错误流的文件对象

- 内部类型:某些由解释器内部使用的类型也被暴露给用户

代码对象:代码对象表示 编译为字节的 可执行 Python 代码,或称 bytecode

帧对象:帧对象表示执行帧

回溯对象:回溯对象表示一个异常的栈跟踪记录

切片对象:slice()创建

静态方法对象:staticmethod()创建

类方法对象:classmethod()创建

### 特殊方法名称

一个类可以通过定义具有特殊名称的方法来实现由特殊语法来发起调用的特定操作(例如算术运算或抽取与切
片);

可以理解为语法糖,使用特定语法时,编译器将编译成调用特定的对象中的特定方法

#### 基本定制

- `object.__new__(cls[, ...])`:调用以创建一个 *cls* 类的新实例

- `object.__init__(self[, ...])`:在实例 (通过 \_\_new\_\_()) 被创建之后,返回调用者之前调


用。基类需显式调用:`super().__init__([args...])`

- `object.__del__(self)`:在实例将被销毁时调用。当解释器退出时不会确保为仍然存在的对象调用
`__del__()`方法。

`del x` 并不直接调用 `x.__del__()` --- 前者会将 `x` 的引用计数减一,而后者仅会在 `x` 的引


用计数变为零时被调用。

- `object.__repr__(self)`:由 repr() 内置函数调用以输出一个对象的“官方”字符串表示

- `object.__str__(self)`:生成一个对象的“非正式”或格式良好的字符串表示

- `object.__bytes__(self)`:通过 bytes 调用以生成一个对象的字节串表示

- `object.__format__(self, format_spec)`:格式化字符串字面值

- 比较

`object.__lt__(self, other)`:x<y
`object.__le__(self, other)`:x<=y
`object.__eq__(self, other)`:x=y
`object.__ne__(self, other)`:x<>y
`object.__gt__(self, other)`:x>y
`object.__ge__(self, other)`:x>=y

- `object.__hash__(self)`:通过内置函数 hash() 调用以对哈希集的成员进行操作

- `object.__bool__(self)`:调用此方法以实现真值检测以及内置的 bool() 操作;应该返回 False 或


True。

#### 自定义属性访问

可以定义下列方法来自定义对类实例属性访问(x.name 的使用、赋值或删除)的具体含义

- `object.__getattr__(self, name)`:当默认属性访问因引发 AttributeError 而失败时被调用

- `object.__getattribute__(self, name)`:此方法会无条件地被调用以实现对类实例属性的访问

- `object.__setattr__(self, name, value)`:此方法在一个属性被尝试赋值时被调用。

- `object.__delattr__(self, name)`:类似于 `__setattr__()` 但其作用为删除而非赋值。此方法


应该仅在 del obj.name 对于该对象有意义时才被实现。

- `object.__dir__(self)`:此方法会在对相应对象调用 dir() 时被调用。返回值必须为一个序列。


dir() 会把返回的序列转换为列表并对其排序。

- 描述器

以下方法仅当一个包含该方法的类(称为 *描述器* 类)的实例出现于一个 *所有者* 类中的时候才会起作用


(该描述器必须在所有者类或其某个上级类的字典中)

`object.__get__(self, instance, owner=None)`

`object.__set__(self, instance, value)`

`object.__delete__(self, instance)`

如果找到的值是定义了某个描述器方法的对象,则 Python 可能会重载默认行为并转而发起调用描述器方法

- `object.__slots__`:这个类变量可赋值为字符串、可迭代对象或由实例使用的变量名组成的字符串序列。
`__slots__` 会为已声明的变量保留空间并阻止自动为每个实例创建 `__dict__` 和 `__weakref__`。

- `classmethod object.__init_subclass__(cls)`:当所在类派生子类时此方法就会被调用。*cls*
将指向新的子类。如果定义为一个普通实例方法,此方法将被隐式地转换为类方法。

- `object.__set_name__(self, owner, name)`:在所有者类 *owner* 被创建时自动调用。

当一个类被创建时,`type.__new__()` 会扫描类变量并对其中带有 `__set_name__()` 钩子的对象执


行回调。

```python
class A:
x = C() # Automatically calls: x.__set_name__(A, 'x')
```

- 元类:类创建过程可通过在定义行传入 `metaclass` 关键字参数,或是通过继承一个包含此参数的现有类


来进行定制。在以下示例中,`MyClass` 和 `MySubclass` 都是 `Meta` 的实例:

```python
class Meta(type):
pass

class MyClass(metaclass=Meta):
pass

class MySubclass(MyClass):
pass
```

当一个类定义被执行时,将发生以下步骤:

- 解析 MRO 条目

`object.__mro_entries__(self, bases)`:If a base that appears in a class


definition is not an instance of type, then an `__mro_entries__()` method is
searched on the base.

- 确定适当的元类

- 如果没有基类且没有显式指定元类,则使用 type()
- 如果给出一个显式元类而且 *不是* type()的实例,则其会被直接用作元类;
- 如果给出一个 type()的实例作为显式元类,或是定义了基类,则使用最近派生的元类。

- 准备类命名空间

一旦确定了适当的元类,就将准备好类的命名空间。 如果元类具有 `__prepare__` 属性,它将以


`namespace = metaclass.__prepare__(name, bases, **kwds)` 的形式被调用(其中如果存在任何
额外关键字参数,则应来自类定义)。

- 执行类主体

类主体会以(类似于) exec(body, globals(), namespace) 的形式被执行。

- 创建类对象

一旦执行类主体完成填充类命名空间,将通过调用 `metaclass(name, bases, namespace,


**kwds)` 创建类对象

#### 自定义实例及子类检查

- `class.__instancecheck__(self, instance):`:如果 instance 应被视为 class 的一个(直接


或间接)实例则返回真值。如果定义了此方法,则会被调用以实现 isinstance(instance, class)。

#### 模拟泛型类型

- `classmethod object.__class_getitem__(cls, key)`:按照 *key* 参数指定的类型返回一个表


示泛型类的专门化对象

#### 模拟可调用对象

- `object.__call__(self[, args...])`:此方法会在实例作为一个函数被“调用”时被调用;如果定义
了此方法,则 `x(arg1, arg2, ...)` 就大致可以被改写为 `type(x).__call__(x, arg1, ...)`。

#### 模拟容器对象

- `object.__len__(self)`:调用此方法以实现内置函数 len()

- `object.__length_hint__(self)`:调用此方法以实现 operator.length_hint()。 应该返回对象


长度的估计值(可能大于或小于实际长度); 此方法纯粹是为了优化性能,并不要求正确无误

- `object.__getitem__(self, key)`:调用此方法以实现 `self[key]`

- `object.__setitem__(self, key, value)`:调用此方法以实现向 `self[key]` 赋值

- `object.__delitem__(self, key)`:调用此方法以实现 `self[key]` 的删除

- `object.__missing__(self, key)`:此方法由 `dict.__getitem__()` 在找不到字典中的键时调


用以实现 dict 子类的 self[key]。

- `object.__iter__(self)`:此方法会在需要为一个容器创建 iterator 时被调用。

- `object.__reversed__(self)`:此方法(如果存在)会被 reversed() 内置函数调用以实现逆向迭代

- `object.__contains__(self, item)`:调用此方法以实现成员检测运算符。如果 *item* 是


*self* 的成员则应返回真,否则返回假。对于映射类型,此检测应基于映射的键而不是值或者键值对。

对于未定义 `__contains__()` 的对象,成员检测将首先尝试通过 `__iter__()` 进行迭代,然后再使


用 `__getitem__()` 的旧式序列迭代协议

#### 模拟数字类型

- `x + y:type(x).__add__(x, y)`

```python
object.__add__(self, other) +
object.__sub__(self, other) -
object.__mul__(self, other) *
object.__matmul__(self, other) @ 矩阵乘法
object.__truediv__(self, other) / 整数除法
object.__floordiv__(self, other) // 浮点数的向下取整除法
object.__mod__(self, other) % 返回余数
object.__divmod__(self, other) 返回商及余数
object.__pow__(self, other[, modulo]) ** 幂次
object.__lshift__(self, other) <<
object.__rshift__(self, other) >>
object.__and__(self, other) &
object.__xor__(self, other) ^
object.__or__(self, other) |
```

- `x - y:type(y).__rsub__(y, x)`

```python
object.__radd__(self, other)
object.__rsub__(self, other)¶
object.__rmul__(self, other)
object.__rmatmul__(self, other)
object.__rtruediv__(self, other)
object.__rfloordiv__(self, other)
object.__rmod__(self, other)
object.__rdivmod__(self, other)
object.__rpow__(self, other[, modulo])
object.__rlshift__(self, other)
object.__rrshift__(self, other)
object.__rand__(self, other)
object.__rxor__(self, other)
object.__ror__(self, other)
```

- `x += y:x = x.__iadd__(y)` 扩展算术赋值

```python
object.__iadd__(self, other) +=
object.__isub__(self, other) -=
object.__imul__(self, other) *=
object.__imatmul__(self, other) @=
object.__itruediv__(self, other) /=
object.__ifloordiv__(self, other) //=
object.__imod__(self, other) %=
object.__ipow__(self, other[, modulo]) **=
object.__ilshift__(self, other) <<=
object.__irshift__(self, other) >>=
object.__iand__(self, other) &=
object.__ixor__(self, other) ^=
object.__ior__(self, other) |=
```

- 其他

```python
一元运算
object.__neg__(self) -
object.__pos__(self) +
object.__abs__(self) abs
object.__invert__(self) ~

object.__complex__(self)
object.__int__(self)
object.__float__(self)
object.__index__(self)
object.__round__(self[, ndigits])
object.__trunc__(self)
object.__floor__(self)
object.__ceil__(self)
```
#### With 语句

上下文管理器 是一个对象,它定义了在执行 with 语句时要建立的运行时上下文;上下文管理器的典型用法包


括保存和恢复各种全局状态,锁定和解锁资源,关闭打开的文件等等

- `object.__enter__(self)`:进入与此对象相关的运行时上下文
- `object.__exit__(self, exc_type, exc_value, traceback)`:退出关联到此对象的运行时上下
文。 各个参数描述了导致上下文退出的异常。 如果上下文是无异常地退出的,三个参数都将为 None。

#### 定制类模式匹配中的位置参数

- `object.__match_args__`

#### 特殊方法查找

对于自定义类来说,特殊方法的隐式发起调用仅保证在其定义于对象类型中时能正确地发挥作用,而不能定义在
对象实例字典中

### 协程

#### 可等待对象

awaitable 对象主要实现了 `__await__()` 方法。 从 async def 函数返回的 协程对象 即为可等待对


- `object.__await__(self)`:必须返回一个 iterator。 应当被用来实现 awaitable 对象。

#### 协程对象

协程对象 属于 awaitable 对象。 协程的执行可以通过调用 `__await__()` 并迭代其结果来控制

- `coroutine.send(value)`:开始或恢复协程的执行
- `coroutine.throw(value)`,`coroutine.throw(type[, value[, traceback]])`:在协程内引
发指定的异常
- `coroutine.close()`:此方法会使得协程清理自身并退出

#### 异步迭代器

异步迭代器 可以在其 `__anext__` 方法中调用异步代码。

异步迭代器可在 async for 语句中使用。

- `object.__aiter__(self)`:必须返回一个 *异步迭代器* 对象

- `object.__anext__(self)`:必须返回一个 可迭代对象 输出迭代器的下一结果值。 当迭代结束时应该


引发 StopAsyncIteration 错误

```python
class Reader:
async def readline(self):
...
def __aiter__(self):
return self

async def __anext__(self):


val = await self.readline()
if val == b'':
raise StopAsyncIteration
return val
```

#### 异步上下文管理器

异步上下文管理器 是 上下文管理器 的一种,它能够在其 `__aenter__` 和 `__aexit__` 方法中暂停执行。

异步上下文管理器可在 async with 语句中使用。

- `object.__aenter__(self)`:在语义上类似于 `__enter__()`,仅有的区别是它必须返回一个 可等
待对象
- `object.__aexit__(self, exc_type, exc_value, traceback)`:在语义上类似于
`__exit__()`,仅有的区别是它必须返回一个 可等待对象

## 执行模型

### 程序的结构

Python 程序 = (代码块)+,代码块(程序文本)= 模块|函数|类定义;

代码块在执行帧中被执行

### 命名与绑定

#### 名称的绑定

*名称* 用于指代对象。 名称是通过名称绑定操作来引入的

如果名称绑定在一个代码块中,则为该代码块的局部变量,除非声明为 nonlocal 或 global。 如果名称绑定


在模块层级,则为全局变量。 (模块代码块的变量既为局部变量又为全局变量。) 如果变量在一个代码块中被使
用但不是在其中定义,则为 自由变量

#### 名称的解析

*作用域* 定义了一个代码块中名称的可见性。 如果代码块中定义了一个局部变量,则其作用域包含该代码块。


如果定义发生于函数代码块中,则其作用域会扩展到该函数所包含的任何代码块,除非有某个被包含代码块引入
了对该名称的不同绑定。

#### 内置命名空间和受限的执行

与一个代码块的执行相关联的内置命名空间实际上是通过在其全局命名空间中搜索名称 `__builtins__` 来找
到的

#### 与动态特性的交互
自由变量的名称解析发生于运行时而不是编译时

### 异常

引发:运行时引发(如:除以 0)或通过 raise 来手动显式引发

捕获:try...except...finally

## 导入系统

一个 module 内的 Python 代码通过 importing 操作就能够访问另一个模块内的代码;

当一个模块首次被导入时,Python 会搜索该模块,如果找到就创建一个 module 对象 1 并初始化它。 如果


指定名称的模块未找到,则会引发 ModuleNotFoundError。 当发起调用导入机制时,Python 会实现多种策
略来搜索指定名称的模块。 这些策略可以通过使用使用下文所描述的多种钩子来加以修改和扩展。

- import:它先搜索指定名称的模块,然后将搜索结果绑定到当前作用域中的名称;底层通过`__import__`
来实现
- `__import__`:直接调用将仅执行模块搜索以及在找到时的模块创建操作
- importlib.import_module():可能会选择绕过 `__import__()` 并使用它们自己的解决方案来实现导
入机制

#### importlib

importlib 模块提供了一个丰富的 API 用来与导入系统进行交互

#### 包

为了帮助组织模块并提供名称层次结构,Python 还引入了 包 的概念。

要注意的一个重点概念是所有包都是模块,但并非所有模块都是包。 或者换句话说,包只是一种特殊的模块。
特别地,任何具有 `__path__` 属性的模块都会被当作是包。

所有模块都有自己的名字。 子包名与其父包名会以点号分隔,如:email.mime.text

- 常规包

常规包通常以一个包含 `__init__.py` 文件的目录形式实现。 当一个常规包被导入时,这个


`__init__.py` 文件会隐式地被执行,它所定义的对象会被绑定到该包命名空间中的名称

```python
parent/
__init__.py
one/
__init__.py
two/
__init__.py
three/
__init__.py
```

导入 `parent.one` 将隐式地执行 `parent/__init__.py` 和 `parent/one/__init__.py`。 后


续导入 `parent.two` 或 `parent.three` 则将分别执行 `parent/two/__init__.py` 和
`parent/three/__init__.py`

- 命名空间包

命名空间包是由多个 部分 构成的,每个部分为父包增加一个子包。 各个部分可能处于文件系统的不同位置。


部分也可能处于 zip 文件中、网络上,或者 Python 在导入期间可以搜索的其他地方。 命名空间包并不一定
会直接对应到文件系统中的对象;它们有可能是无实体表示的虚拟模块。

#### 搜索

为了开始搜索,Python 需要被导入模块(或者包,对于当前讨论来说两者没有差别)的完整 限定名称。 此名


称可以来自 import 语句所带的各种参数,或者来自传给 importlib.import_module() 或
`__import__()` 函数的形参。

- 模块缓存

在导入搜索期间首先会被检查的地方是 sys.modules。 这个映射起到缓存之前导入的所有模块的作用(包括


其中间路径)。 因此如果之前导入过 foo.bar.baz,则 sys.modules 将包含 foo, foo.bar 和
foo.bar.baz 条目。 每个键的值就是相应的模块对象

sys.modules 是可写的

- 查找器和加载器

如果指定名称的模块在 sys.modules 找不到,则将发起调用 Python 的导入协议以查找和加载该模块。


此协议由两个概念性模块构成,即 查找器 和 加载器。 查找器的任务是确定是否能使用其所知的策略找到该名
称的模块。 同时实现这两种接口的对象称为 导入器 —— 它们在确定能加载所需的模块时会返回其自身。

- 导入钩子

导入机制被设计为可扩展;其中的基本机制是 导入钩子。 导入钩子有两种类型: 元钩子 和 导入路径钩子

元钩子的注册是通过向 sys.meta_path 添加新的查找器对象

导入路径钩子的注册是通过向 sys.path_hooks 添加新的可调用对象

- 元路径

当指定名称的模块在 sys.modules 中找不到时,Python 会接着搜索 sys.meta_path,其中包含元路径


查找器对象列表

元路径查找器必须实现名为 find_spec() 的方法,该方法接受三个参数:名称、导入路径和目标模块(可


选)

#### 加载

当一个模块说明被找到时,导入机制将在加载该模块时使用它(及其所包含的加载器)

- 加载器
模块加载器提供关键的加载功能:模块执行。导入机制调用 importlib.abc.Loader.exec_module() 方
法并传入一个参数来执行模块对象。 从 exec_module() 返回的任何值都将被忽略。

create_module():模块加载器可以选择通过实现 create_module() 方法在加载期间创建模块对象。


它接受一个参数,即模块规格说明,并返回新的模块对象供加载期间使用

exec_module():执行模块

- 子模块

当使用任意机制 (例如 importlib API, import 及 import-from 语句或者内置的


`__import__())` 加载一个子模块时,父模块的命名空间中会添加一个对子模块对象的绑定。

```python
spam/
__init__.py
foo.py
```

` spam/__init__.py`:

```python
from .foo import Foo
```

```python
import spam
>>> spam.foo
<module 'spam.foo' from '/tmp/imports/spam/foo.py'>
>>> spam.Foo
<class 'spam.foo.Foo'>
```

- 模块规格说明

导入机制在导入期间会使用有关每个模块的多种信息,特别是加载之前。 大多数信息都是所有模块通用的。
模块规格说明的目的是基于每个模块来封装这些导入相关信息。

在导入期间使用规格说明可允许状态在导入系统各组件之间传递,例如在创建模块规格说明的查找器和执行模
块的加载器之间。 最重要的一点是,它允许导入机制执行加载的样板操作,在没有模块规格说明的情况下这是加
载器的责任。

模块的规格说明会作为模块对象的 `__spec__` 属性对外公开

- 导入相关的模块属性

`__name__`:【必须】模块的唯一标识名称

`__loader__`:【必须】被设为导入系统在加载模块时使用的加载器对象

`__package__`:【必须】其取值必须为一个字符串,但可以与 `__name__` 取相同的值。 当模块是包时,


其 `__package__` 值应该设为其 `__name__` 值。 当模块不是包时,对于最高层级模块 `__package__`
应该设为空字符串,对于子模块则应该设为其父包名
`__spec__`:【必须】设为在导入模块时要使用的模块规格说明

`__path__`:如果模块为包(不论是正规包还是命名空间包),则必须设置模块对象的 `__path__` 属性。


属性值必须为可迭代对象,但如果 `__path__` 没有进一步的用处则可以为空。

`__file__`:【可选】It indicates the pathname of the file from which the module
was loaded (if loaded from a file), or the pathname of the shared library file for
extension modules loaded dynamically from a shared library.

- `module.__path__`

根据定义,如果一个模块具有 `__path__` 属性,它就是包;

命名空间包不再需要提供仅包含 `__path__` 操控代码的 `__init__.py` 文件;导入机制会自动为命名


空间包正确地设置 `__path__`

- 模块的 repr

默认情况下,全部模块都具有一个可用的 repr,但是你可以依据上述的属性设置,在模块的规格说明中更为
显式地控制模块对象的 repr。

如果模块具有 spec (`__spec__`),导入机制将尝试用它来生成一个 repr。 如果生成失败或找不到


spec,导入系统将使用模块中的各种可用信息来制作一个默认 repr。 它将尝试使用 `module.__name__`,
`module.__file__` 以及 `module.__loader__` 作为 repr 的输入,并将任何丢失的信息赋为默认值。

- 已缓存字节码的失效

在 Python 从 `.pyc` 文件加载已缓存字节码之前,它会检查缓存是否由最新的 `.py` 源文件所生成。


默认情况下,Python 通过在所写入缓存文件中保存源文件的最新修改时间戳和大小来实现这一点。 在运行时,
导入系统会通过比对缓存文件中保存的元数据和源文件的元数据确定该缓存的有效性。

#### 基于路径的查找器

它会搜索包含一个 路径条目 列表的 import path。 每个路径条目指定一个用于搜索模块的位置。

- 路径条目查找器

path based finder 会负责查找和加载通过 path entry 字符串来指定位置的 Python 模块和包。 多


数路径条目所指定的是文件系统中的位置,但它们并不必受限于此

sys.path:contains a list of strings providing search locations for modules and


packages

sys.path_importer_cache:the path based finder maintains a cache mapping path


entries to path entry finders

sys.path_hooks:如果路径条目不存在于缓存中,基于路径的查找器会迭代 sys.path_hooks 中的每个


可调用对象

- 路径条目查找器协议
为了支持模块和已初始化包的导入,也为了给命名空间包提供组成部分,路径条目查找器必须实现
find_spec() 方法。

#### 替换标准导入系统

替换整个导入系统的最可靠机制是移除 sys.meta_path 的默认内容,,将其完全替换为自定义的元路径钩子

一个可行的方式是仅改变导入语句的行为而不影响访问导入系统的其他 API,那么替换内置的
`__import__()` 函数可能就够了。 这种技巧也可以在模块层级上运用,即只在某个模块内部改变导入语句的
行为。

想要选择性地预先防止在元路径上从一个钩子导入某些模块(而不是完全禁用标准导入系统),只需直接从
find_spec() 引发 ModuleNotFoundError 而非返回 None 就足够了。 返回后者表示元路径搜索应当继续,
而引发异常则会立即终止搜索。

#### 包相对导入

相对导入使用前缀点号。 一个前缀点号表示相对导入从当前包开始。 两个或更多前缀点号表示对当前包的上级


包的相对导入,第一个点号之后的每个点号代表一级

绝对导入可以使用 import <> 或 from <> import <> 语法,但相对导入只能使用第二种形式。

#### 有关`__main__`的特殊事项

`__main__` 模块是在解释器启动时直接初始化的,与 sys 和 builtins 很类似。 但是,与那两者不同,


它并不被严格归类为内置模块。 这是因为 `__main__` 被初始化的方式依赖于发起调用解释器所附带的旗标和
其他选项。

- `__main__.__spec__`:根据 `__main__`被初始化的方式,`.__spec__` 会被设置相应值或是


`None`

如果想要让 `__main__` 中的元数据生效,请使用 -m 开关

## 表达式

### 算术转换

- 如果任一参数为复数,另一参数会被转换为复数;
- 否则,如果任一参数为浮点数,另一参数会被转换为浮点数;
- 否则,两者应该都为整数,不需要进行转换。

### 原子

“原子”指表达式的最基本构成元素。 最简单的原子是标识符和字面值。 以圆括号、方括号或花括号包括的形式


在语法上也被归类为原子

```python
atom ::= identifier | literal | enclosure
enclosure ::= parenth_form | list_display | dict_display | set_display
| generator_expression | yield_atom
```
#### 标识符

作为原子出现的标识符叫做名称

私有名称转换:当以文本形式出现在类定义中的一个标识符以两个或更多下划线开头并且不以两个或更多下划线
结尾,它会被视为该类的 *私有名称*;出现在一个名为 `Ham` 的类中的标识符 `__spam` 会被转换为
`_Ham__spam`

#### 字面值

Python 支持字符串和字节串字面值,以及几种数字字面值

```
literal ::= stringliteral | bytesliteral
| integer | floatnumber | imagnumber
```

#### 带圆括号的形式

带圆括号的形式是包含在圆括号中的可选表达式列表

```
parenth_form ::= "(" [starred_expression] ")"
```

如果该列表包含至少一个逗号,它会产生一个元组;否则,它会产生该表达式列表所对应的单一表达式。

#### 列表、集合与字典的显示

为了构建列表、集合或字典,Python 提供了名为“显示”的特殊句法,每个类型各有两种形式:

- 第一种是显式地列出容器内容
- 第二种是通过一组循环和筛选指令计算出来,称为 *推导式*。

推导式的常用句法元素为:

```
comprehension ::= assignment_expression comp_for
comp_for ::= ["async"] "for" target_list "in" or_test [comp_iter]
comp_iter ::= comp_for | comp_if
comp_if ::= "if" or_test [comp_iter]
```

#### 列表显示

列表显示是一个用方括号括起来的可能为空的表达式系列

```python
list_display ::= "[" [starred_list | comprehension] "]"
```

#### 集合显示
集合显示是用花括号标明的,与字典显示的区别在于没有冒号分隔的键和值:

```
set_display ::= "{" (starred_list | comprehension) "}"
```

#### 字典显示

A dictionary display is a possibly empty series of dict items (key/value pairs)


enclosed in curly braces

```
dict_display ::= "{" [dict_item_list | dict_comprehension] "}"
dict_item_list ::= dict_item ("," dict_item)* [","]
dict_item ::= expression ":" expression | "**" or_expr
dict_comprehension ::= expression ":" expression comp_for
```

#### 生成器表达式

生成器表达式是用圆括号括起来的紧凑形式生成器标注

```
generator_expression ::= "(" expression comp_for ")"
```

#### yield 表达式

```
yield_atom ::= "(" yield_expression ")"
yield_expression ::= "yield" [expression_list | "from" expression]
```

- 生成器-迭代器的方法

`generator.__next__()`:开始一个生成器函数的执行或是从上次执行 yield 表达式的位置恢复执行

`generator.send(value)`:恢复执行并向生成器函数“发送”一个值。 *value* 参数将成为当前


yield 表达式的结果

`generator.throw(value)`

`generator.throw(type[, value[, traceback]])`:在生成器暂停的位置引发一个异常,并返回该


生成器函数所产生的下一个值

`generator.close()`:在生成器函数暂停的位置引发 GeneratorExit

```python
def echo(value=None):
... print("Execution starts when 'next()' is called for the first time.")
... try:
... while True:
... try:
... value = (yield value)
... except Exception as e:
... value = e
... finally:
... print("Don't forget to clean up when 'close()' is called.")
...
>>> generator = echo(1)
>>> print(next(generator))
Execution starts when 'next()' is called for the first time.
1
>>> print(next(generator))
None
>>> print(generator.send(2))
2
>>> generator.throw(TypeError, "spam")
TypeError('spam',)
>>> generator.close()
Don't forget to clean up when 'close()' is called.
```

- 异步生成器函数

在一个使用 async def 定义的函数或方法中出现的 yield 表达式会进一步将该函数定义为一个


asynchronous generator 函数

- 异步生成器-迭代器方法

`coroutine agen.__anext__()`:返回一个可等待对象,它在运行时会开始执行该异步生成器或是从上
次执行的 yield 表达式位置恢复执行。此方法通常是通过 async for 循环隐式地调用。

`coroutine agen.asend(value)`:返回一个可等待对象,它在运行时会恢复该异步生成器的执行

`coroutine agen.athrow(value)`

`coroutine agen.athrow(type[, value[, traceback]])`:返回一个可等待对象,它会在异步生成


器暂停的位置引发 type 类型的异常,并返回该生成器函数所产生的下一个值,其值为所引发的
StopIteration 异常

`coroutine agen.aclose()`:返回一个可等待对象,它会在运行时向异步生成器函数暂停的位置抛入一
个 GeneratorExit。

### 原型

原型代表编程语言中最紧密绑定的操作。 它们的句法如下:

```
primary ::= atom | attributeref | subscription | slicing | call
```

#### 属性引用

属性引用是后面带有一个句点加一个名称的原型:

```
attributeref ::= primary "." identifier
```
产生过程可通过重载 `__getattr__()` 方法来自定义

#### 抽取

对一个 容器类 的实例执行抽取操作通常将会从该容器中选取一个元素。 而对一个 泛型类 执行抽取操作通常将


会返回一个 GenericAlias 对象。

```
subscription ::= primary "[" expression_list "]"
```

一个对象可通过同时定义 `__getitem__()` 和 `__class_getitem__()` 或其中之一来支持抽取操作。

#### 切片

切片就是在序列对象(字符串、元组或列表)中选择某个范围内的项。 切片可被用作表达式以及赋值或 del 语


句的目标。 切片的句法如下:

```python
slicing ::= primary "[" slice_list "]"
slice_list ::= slice_item ("," slice_item)* [","]
slice_item ::= expression | proper_slice
proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]
lower_bound ::= expression
upper_bound ::= expression
stride ::= expression
```

#### 调用

所谓调用就是附带可能为空的一系列 参数 来执行一个可调用对象 (例如 function):

```
call ::= primary "(" [argument_list [","] | comprehension] ")"
argument_list ::= positional_arguments ["," starred_and_keywords]
["," keywords_arguments]
| starred_and_keywords ["," keywords_arguments]
| keywords_arguments
positional_arguments ::= positional_item ("," positional_item)*
positional_item ::= assignment_expression | "*" expression
starred_and_keywords ::= ("*" expression | keyword_item)
("," "*" expression | "," keyword_item)*
keywords_arguments ::= (keyword_item | "**" expression)
("," keyword_item | "," "**" expression)*
keyword_item ::= identifier "=" expression
```

此原型必须求值为一个可调用对象(用户定义的函数,内置函数,内置对象的方法,类对象,类实例的方法以及
任何具有 `__call__()` 方法的对象都是可调用对象)。 所有参数表达式将在尝试调用前被求值。

如果存在比正式参数空位多的位置参数,将会引发 `TypeError`异常,除非有一个正式参数使用了
`*identifier` 句法;在此情况下,该正式参数将接受一个包含了多余位置参数的元组(如果没有多余位置参
数则为一个空元组)。

如果任何关键字参数没有与之对应的正式参数名称,将会引发
[`TypeError`](https://docs.python.org/zh-cn/3/library/exceptions.html#TypeError) 异
常,除非有一个正式参数使用了 `**identifier` 句法,该正式参数将接受一个包含了多余关键字参数的字典
(使用关键字作为键而参数值作为与键对应的值),如果没有多余关键字参数则为一个(新的)空字典。

如果函数调用中出现了 `*expression` 句法,`expression` 必须求值为一个


[iterable](https://docs.python.org/zh-cn/3/glossary.html#term-iterable)。 来自该可迭
代对象的元素会被当作是额外的位置参数。 对于 `f(x1, x2, *y, x3, x4)` 调用,如果 *y* 求值为一个
序列 *y1*, ..., *yM*,则它就等价于一个带有 M+4 个位置参数 *x1*, *x2*, *y1*, ..., *yM*,
*x3*, *x4* 的调用。

如果类型为---

- 用户自定义函数:

函数的代码块会被执行,并向其传入参数列表。 代码块所做的第一件事是将正式形参绑定到对应参数;相关描
述参见 [函数定
义](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#function) 一节。
当代码块执行
[`return`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#return) 语句
时,由其指定函数调用的返回值。

- 内置函数或方法:

具体结果依赖于解释器;有关内置函数和方法的描述参见 [内置函数](https://docs.python.org/zh-
cn/3/library/functions.html#built-in-funcs)。

- 类对象:

返回该类的一个新实例。

- 类实例方法:

调用相应的用户自定义函数,向其传入的参数列表会比调用的参数列表多一项:该实例将成为第一个参数。

- 类实例:

该类必须定义有 `__call__()` 方法;作用效果将等价于调用该方法。

#### await 表达式

挂起 [coroutine](https://docs.python.org/zh-cn/3/glossary.html#term-coroutine) 的执
行以等待一个 [awaitable](https://docs.python.org/zh-cn/3/glossary.html#term-
awaitable) 对象。 只能在 [coroutine
function](https://docs.python.org/zh-cn/3/glossary.html#term-coroutine-function) 内
部使用。

```
await_expr ::= "await" primary
```
#### 幂运算符

幂运算符的绑定比在其左侧的一元运算符更紧密;但绑定紧密程度不及在其右侧的一元运算符。 句法如下:

```
power ::= (await_expr | primary) ["**" u_expr]
```

因此,在一个未加圆括号的幂运算符和单目运算符序列中,运算符将从右向左求值(这不会限制操作数的求值顺
序): `-1**2` 结果将为 `-1`。

幂运算符与附带两个参数调用内置
[`pow()`](https://docs.python.org/zh-cn/3/library/functions.html#pow) 函数具有相同的
语义:结果为对其左参数进行其右参数所指定幂次的乘方运算。 数值参数会先转换为相同类型,结果也为转换后
的类型。

#### 一元运算及位运算

所有算术和位运算具有相同的优先级:

```
u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr
```

一元的 `-` (负值) 运算符会产生其数字参数的负值;该运算可通过 `__neg__()` 特殊方法来重载。

一元的 `+` (正值) 运算符会原样输出其数字参数;该运算可通过 `__pos__()` 特殊方法来重载。

一元的 `~` (取反) 运算符会对其整数参数按位取反。 `x` 的按位取反被定义为 `-(x+1)`。 它只作用于整


数或是重载了 `__invert__()` 特殊方法的自定义对象。

在所有三种情况下,如果参数的类型不正确,将引发 [`TypeError`](https://docs.python.org/zh-
cn/3/library/exceptions.html#TypeError) 异常

#### 二元算术运算符

二元算术运算符遵循传统的优先级。 请注意某些此类运算符也作用于特定的非数字类型。 除幂运算符以外只有


两个优先级别,一个作用于乘法型运算符,另一个作用于加法型运算符:

```
m_expr ::= u_expr | m_expr "*" u_expr | m_expr "@" m_expr |
m_expr "//" u_expr | m_expr "/" u_expr |
m_expr "%" u_expr
a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr
```

运算符 `*` (乘) 将输出其参数的乘积。 两个参数或者必须都为数字,或者一个参数必须为整数而另一个参数


必须为序列。 在前一种情况下,两个数字将被转换为相同类型然后相乘。 在后一种情况下,将执行序列的重复;
重复因子为负数将输出空序列。

此运算可使用特殊的 `__mul__()` 和 `__rmul__()` 方法来自定义。


运算符 `@` (at) 的目标是用于矩阵乘法。 没有内置 Python 类型实现此运算符。

`x == (x//y)*y + (x%y)`

`divmod(x, y) == (x//y, x%y)`

#### 移位运算

移位运算的优先级低于算术运算:

```
shift_expr ::= a_expr | shift_expr ("<<" | ">>") a_expr
```

这些运算符接受整数参数。 它们会将第一个参数左移或右移第二个参数所指定的比特位数。

此运算可使用特殊的 `__lshift__()` 和 `__rshift__()` 方法来自定义。

右移 *n* 位被定义为被 `pow(2,n)` 整除。 左移 *n* 位被定义为乘以 `pow(2,n)`。

#### 二元位运算

三种位运算具有各不相同的优先级:

```
and_expr ::= shift_expr | and_expr "&" shift_expr
xor_expr ::= and_expr | xor_expr "^" and_expr
or_expr ::= xor_expr | or_expr "|" xor_expr
```

`&` 运算符会对其参数执行按位 AND,参数必须都为整数或者其中之一必须为重载了 `__and__()` 或


`__rand__()` 特殊方法的自定义对象。

`^` 运算符会对其参数执行按位 XOR (异 OR),参数必须都为整数或者其中之一必须为重载了 `__xor__()`


或 `__rxor__()` 特殊方法的自定义对象。

`|` 运算符会对其参数执行按位 (合并) OR,参数必须都为整数或者其中之一必须为重载了 `__or__()` 或


`__ror__()` 特殊方法的自定义对象。

#### 比较运算

与 C 不同,Python 中所有比较运算的优先级相同,低于任何算术、移位或位运算。 另一个与 C 不同之处在


于 `a < b < c` 这样的表达式会按传统算术法则来解读:

```
comparison ::= or_expr (comp_operator or_expr)*
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="
| "is" ["not"] | ["not"] "in"
```

比较运算会产生布尔值: `True` 或 `False`。 自定义的 *富比较方法* 可能返回非布尔值。 在此情况下


Python 将在布尔运算上下文中对该值调用
[`bool()`](https://docs.python.org/zh-cn/3/library/functions.html#bool)。
比较运算可以任意串连,例如 `x < y <= z` 等价于 `x < y and y <= z`,除了 `y` 只被求值一次(但
在两种写法下当 `x < y` 值为假时 `z` 都不会被求值)。

正式的说法是这样:如果 *a*, *b*, *c*, ..., *y*, *z* 为表达式而 *op1*, *op2*, ..., *opN*
为比较运算符,则 `a op1 b op2 c ... y opN z` 就等价于 `a op1 b and b op2 c and ... y
opN z`,不同点在于每个表达式最多只被求值一次。

请注意 `a op1 b op2 c` 不意味着在 *a* 和 *c* 之间进行任何比较,因此,如 `x < y > z` 这样的写
法是完全合法的(虽然也许不太好看)

- 值比较

运算符 `<`, `>`, `==`, `>=`, `<=` 和 `!=` 将比较两个对象的值。 两个对象不要求为相同类型;

不同的类型对于值比较有不同的比较算法

- 成员检测运算

运算符 [`in`](https://docs.python.org/zh-cn/3/reference/expressions.html#in) 和
[`not in`](https://docs.python.org/zh-cn/3/reference/expressions.html#not-in) 用于成
员检测。 如果 *x* 是 *s* 的成员则 `x in s` 求值为 `True`,否则为 `False`。 `x not in s` 返
回 `x in s` 取反后的值。 所有内置序列和集合类型以及字典都支持此运算,对于字典来说 `in` 检测其是
否有给定的键。 对于 list, tuple, set, frozenset, dict 或 collections.deque 这样的容器类型,
表达式 `x in y` 等价于 `any(x is e or x == e for e in y)`。

对于定义了 `__contains__()` 方法的用户自定义类来说,如果 `y.__contains__(x)` 返回真值则


`x in y` 返回 `True`,否则返回 `False`。

- 标识号比较

运算符 [`is`](https://docs.python.org/zh-cn/3/reference/expressions.html#is) 和
[`is not`](https://docs.python.org/zh-cn/3/reference/expressions.html#is-not) 用于检
测对象的标识号:当且仅当 *x* 和 *y* 是同一对象时 `x is y` 为真。 一个对象的标识号可使用
[`id()`](https://docs.python.org/zh-cn/3/library/functions.html#id) 函数来确定。 `x
is not y` 会产生相反的逻辑值

#### 布尔运算

```
or_test ::= and_test | or_test "or" and_test
and_test ::= not_test | and_test "and" not_test
not_test ::= comparison | "not" not_test
```

在执行布尔运算的情况下,或是当表达式被用于流程控制语句时,以下值会被解析为假值: `False`, `None`,


所有类型的数字零,以及空字符串和空容器(包括字符串、元组、列表、字典、集合与冻结集合)。 所有其他值
都会被解析为真值。 用户自定义对象可通过提供 `__bool__()` 方法来定制其逻辑值。

运算符 [`not`](https://docs.python.org/zh-cn/3/reference/expressions.html#not) 将在其


参数为假值时产生 `True`,否则产生 `False`。
表达式 `x and y` 首先对 *x* 求值;如果 *x* 为假则返回该值;否则对 *y* 求值并返回其结果值。

表达式 `x or y` 首先对 *x* 求值;如果 *x* 为真则返回该值;否则对 *y* 求值并返回其结果值。

请注意 [`and`](https://docs.python.org/zh-cn/3/reference/expressions.html#and) 和
[`or`](https://docs.python.org/zh-cn/3/reference/expressions.html#or) 都不限制其返回
的值和类型必须为 `False` 和 `True`,而是返回最后被求值的操作数。 此行为是有必要的,例如假设 `s`
为一个当其为空时应被替换为某个默认值的字符串,表达式 `s or 'foo'` 将产生希望的值。 由于 [`not`]
(https://docs.python.org/zh-cn/3/reference/expressions.html#not) 必须创建一个新值,不
论其参数为何种类型它都会返回一个布尔值(例如,`not 'foo'` 结果为 `False` 而非 `''`。)

#### 赋值表达式

```
assignment_expression ::= [identifier ":="] expression
```

赋值表达式(有时又被称为“命名表达式”或“海象表达式”)将一个
[`expression`](https://docs.python.org/zh-cn/3/reference/expressions.html#grammar-
token-python-grammar-expression) 赋值给一个
[`identifier`](https://docs.python.org/zh-cn/3/reference/lexical_analysis.html#gram
mar-token-python-grammar-identifier),同时还会返回
[`expression`](https://docs.python.org/zh-cn/3/reference/expressions.html#grammar-
token-python-grammar-expression) 的值。

#### 条件表达式

```
conditional_expression ::= or_test ["if" or_test "else" expression]
expression ::= conditional_expression | lambda_expr
```

条件表达式(有时称为“三元运算符”)在所有 Python 运算中具有最低的优先级。

表达式 `x if C else y` 首先是对条件 *C* 而非 *x* 求值。 如果 *C* 为真,*x* 将被求值并返回其值;


否则将对 *y* 求值并返回其值。

#### lambda 表达式

```
lambda_expr ::= "lambda" [parameter_list] ":" expression
```

#### 表达式列表

```
expression_list ::= expression ("," expression)* [","]
starred_list ::= starred_item ("," starred_item)* [","]
starred_expression ::= expression | (starred_item ",")* [starred_item]
starred_item ::= assignment_expression | "*" or_expr
```

除了作为列表或集合显示的一部分,包含至少一个逗号的表达式列表将生成一个元组。 元组的长度就是列表中表
达式的数量。 表达式将从左至右被求值。

一个星号 `*` 表示 *可迭代拆包*。 其操作数必须为一个 [iterable](https://docs.python.org/zh-


cn/3/glossary.html#term-iterable)。 该可迭代对象将被拆解为迭代项的序列,并被包含于在拆包位置
上新建的元组、列表或集合之中。

- 求值顺序

Python 按从左至右的顺序对表达式求值。 但注意在对赋值操作求值时,右侧会先于左侧被求值。

在以下几行中,表达式将按其后缀的算术优先顺序被求值。:

```
expr1, expr2, expr3, expr4
(expr1, expr2, expr3, expr4)
{expr1: expr2, expr3: expr4}
expr1 + expr2 * (expr3 - expr4)
expr1(expr2, expr3, *expr4, **expr5)
expr3, expr4 = expr1, expr2
```

- 运算符优先级(从高到低)

| 运算符 | 描述
|
| :-----------------------------------------------------------
| :----------------------------------------------------------- |
| `(expressions...)`,`[expressions...]`, `{key: value...}`, `{expressions...}` |
绑定或加圆括号的表达式,列表显示,字典显示,集合显示 |
| `x[index]`, `x[index:index]`, `x(arguments...)`, `x.attribute` | 抽取,切片,调用,
属性引用 |
| [`await x`](https://docs.python.org/zh-cn/3/reference/expressions.html#await) |
await 表达式 |
| `**` | 乘方 [5]
(https://docs.python.org/zh-cn/3/reference/expressions.html#id21) |
| `+x`, `-x`, `~x` | 正,负,按位非 NOT
|
| `*`, `@`, `/`, `//`, `%` | 乘,矩阵乘,除,整
除,取余 [6](https://docs.python.org/zh-cn/3/reference/expressions.html#id22) |
| `+`, `-` | 加和减
|
| `<<`, `>>` | 移位
|
| `&` | 按位与 AND
|
| `^` | 按位异或 XOR
|
| `|` | 按位或 OR
|
| [`in`](https://docs.python.org/zh-cn/3/reference/expressions.html#in), [`not
in`](https://docs.python.org/zh-cn/3/reference/expressions.html#not-in), [`is`]
(https://docs.python.org/zh-cn/3/reference/expressions.html#is), [`is not`]
(https://docs.python.org/zh-cn/3/reference/expressions.html#is-not), `<`, `<=`,
`>`, `>=`, `!=`, `==` | 比较运算,包括成员检测和标识号检测 |
| [`not x`](https://docs.python.org/zh-cn/3/reference/expressions.html#not) | 布
尔逻辑非 NOT |
| [`and`](https://docs.python.org/zh-cn/3/reference/expressions.html#and) | 布尔逻
辑与 AND |
| [`or`](https://docs.python.org/zh-cn/3/reference/expressions.html#or) | 布尔逻辑
或 OR |
| [`if`](https://docs.python.org/zh-cn/3/reference/expressions.html#if-expr) --
`else` | 条件表达式 |
| [`lambda`](https://docs.python.org/zh-cn/3/reference/expressions.html#lambda) |
lambda 表达式 |
| `:=` | 赋值表达式
|

## 简单语句

简单语句由一个单独的逻辑行构成。 多条简单语句可以存在于同一行内并以分号分隔。 简单语句的句法为:

```python
simple_stmt ::= expression_stmt
| assert_stmt
| assignment_stmt
| augmented_assignment_stmt
| annotated_assignment_stmt
| pass_stmt
| del_stmt
| return_stmt
| yield_stmt
| raise_stmt
| break_stmt
| continue_stmt
| import_stmt
| future_stmt
| global_stmt
| nonlocal_stmt
```

### 表达式语句

表达式语句用于计算和写入值(大多是在交互模式下),或者(通常情况)调用一个过程 (过程就是不返回有意
义结果的函数;在 Python 中,过程的返回值为 `None`)。 表达式语句的其他使用方式也是允许且有特定用
处的。 表达式语句的句法为:

```
expression_stmt ::= starred_expression
```

表达式语句会对指定的表达式列表(也可能为单一表达式)进行求值

### 赋值语句

赋值语句用于将名称(重)绑定到特定值,以及修改属性或可变对象的成员项:

```
assignment_stmt ::= (target_list "=")+ (starred_expression | yield_expression)
target_list ::= target ("," target)* [","]
target ::= identifier
| "(" [target_list] ")"
| "[" [target_list] "]"
| attributeref
| subscription
| slicing
| "*" target
```

### 增强赋值语句

增强赋值语句就是在单个语句中将二元运算和赋值语句合为一体:

```
augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)
augtarget ::= identifier | attributeref | subscription | slicing
augop ::= "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" |
"**="
| ">>=" | "<<=" | "&=" | "^=" | "|="
```

### 带标注的赋值语句

[标注](https://docs.python.org/zh-cn/3/glossary.html#term-variable-annotation) 赋值
就是在单个语句中将变量或属性标注和可选的赋值语句合为一体:

```
annotated_assignment_stmt ::= augtarget ":" expression
["=" (starred_expression | yield_expression)]
```

### assert 语句

assert 语句是在程序中插入调试性断言的简便方式:

```
assert_stmt ::= "assert" expression ["," expression]
```

简单形式 `assert expression` 等价于

```
if __debug__:
if not expression: raise AssertionError
```

扩展形式 `assert expression1, expression2` 等价于

```
if __debug__:
if not expression1: raise AssertionError(expression2)
```

编译时指定编译选项(-o),`__debug__`将为 False
### pass 语句

```
pass_stmt ::= "pass"
```

[`pass`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#pass) 是一个空
操作 --- 当它被执行时,什么都不发生。 它适合当语法上需要一条语句但并不需要执行任何代码时用来临时占
位,例如:

```
def f(arg): pass # a function that does nothing (yet)

class C: pass # a class with no methods (yet)


```

### del 语句

```
del_stmt ::= "del" target_list
```

目标列表的删除将从左至右递归地删除每一个目标。

名称的删除将从局部或全局命名空间中移除该名称的绑定,具体作用域的确定是看该名称是否有在同一代码块的
[`global`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#global) 语句
中出现。 如果该名称未被绑定,将会引发
[`NameError`](https://docs.python.org/zh-cn/3/library/exceptions.html#NameError)。

属性引用、抽取和切片的删除会被传递给相应的原型对象;删除一个切片基本等价于赋值为一个右侧类型的空切
片(但即便这一点也是由切片对象决定的)。

### return 语句

```
return_stmt ::= "return" [expression_list]
```

[`return`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#return) 在语
法上只会出现于函数定义所嵌套的代码,不会出现于类定义所嵌套的代码。

如果提供了表达式列表,它将被求值,否则以 `None` 替代。

[`return`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#return) 会离
开当前函数调用,并以表达式列表 (或 `None`) 作为返回值。

当 [`return`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#return)
将控制流传出一个带有
[`finally`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#finally)
子句的 [`try`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#try) 语
句时,该 `finally` 子句会先被执行然后再真正离开该函数。
### yield 语句

```
yield_stmt ::= yield_expression
```

[`yield`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#yield) 语句在
语义上等同于 [yield 表达
式](https://docs.python.org/zh-cn/3/reference/expressions.html#yieldexpr)。 yield 语
句可用来省略在使用等效的 yield 表达式语句时所必须的圆括号。

### raise 语句

```
raise_stmt ::= "raise" [expression ["from" expression]]
```

如果没有提供表达式,则
[`raise`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#raise) 会重新
引发当前正在处理的异常,它也被称为 *活动的异常*。 如果当前没有活动的异常,则会引发
[`RuntimeError`](https://docs.python.org/zh-cn/3/library/exceptions.html#RuntimeErr
or) 来提示发生了错误

`from` 子句用于异常串连:如果有该子句,则第二个 *表达式* 必须为另一个异常类或实例。 如果第二个表


达式是一个异常实例,它将作为可写的 `__cause__` 属性被关联到所引发的异常。 如果该表达式是一个异常
类,这个类将被实例化且所生成的异常实例将作为 `__cause__` 属性被关联到所引发的异常。

吃掉异常

```
try:
... print(1 / 0)
... except:
... raise RuntimeError("Something bad happened") from None
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened
```

### break 语句

```
break_stmt ::= "break"
```

[`break`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#break) 在语法
上只会出现于
[`for`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#for) 或
[`while`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#while) 循环
所嵌套的代码,但不会出现于该循环内部的函数或类定义所嵌套的代码。

它会终结最近的外层循环,如果循环有可选的 `else` 子句,也会跳过该子句。


### continue 语句

```
continue_stmt ::= "continue"
```

[`continue`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#continue)
在语法上只会出现于
[`for`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#for) 或
[`while`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#while) 循环
所嵌套的代码中,但不会出现于该循环内部的函数或类定义中。 它会继续执行最近的外层循环的下一个轮次。

### import 语句

```python
import_stmt ::= "import" module ["as" identifier] ("," module ["as"
identifier])*
| "from" relative_module "import" identifier ["as" identifier]
("," identifier ["as" identifier])*
| "from" relative_module "import" "(" identifier ["as"
identifier]
("," identifier ["as" identifier])* [","] ")"
| "from" relative_module "import" "*"
module ::= (identifier ".")* identifier
relative_module ::= "."* module | "."+
```

基本的 import 语句(不带


[`from`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#from) 子句)会
分两步执行:

1. 查找一个模块,如果有必要还会加载并初始化模块。
2. 在局部命名空间中为
[`import`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#import) 语句
发生位置所处的作用域定义一个或多个名称

如果成功获取到请求的模块,则可以通过以下三种方式一之在局部命名空间中使用它:

- 模块名后使用 `as` 时,直接把 `as` 后的名称与导入模块绑定。


- 如果没有指定其他名称,且被导入的模块为最高层级模块,则模块的名称将被绑定到局部命名空间作为对所导
入模块的引用。
- 如果被导入的模块 *不是* 最高层级模块,则包含该模块的最高层级包的名称将被绑定到局部命名空间作为对
该最高层级包的引用。 所导入的模块必须使用其完整限定名称来访问而不能直接访问。

[`from`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#from) 形式使用
的过程略微繁复一些:

1. 查找 [`from`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#from)
子句中指定的模块,如有必要还会加载并初始化模块;

2. 对于
[`import`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#import) 子句
中指定的每个标识符:

1. 检查被导入模块是否有该名称的属性

2. 如果没有,尝试导入具有该名称的子模块,然后再次检查被导入模块是否有该属性

3. 如果未找到该属性,则引发
[`ImportError`](https://docs.python.org/zh-cn/3/library/exceptions.html#ImportError
)。

4. 否则的话,将对该值的引用存入局部命名空间,如果有 `as` 子句则使用其指定的名称,否则使用该属


性的名称

```
import foo # foo imported and bound locally
import foo.bar.baz # foo, foo.bar, and foo.bar.baz imported, foo
bound locally
import foo.bar.baz as fbb # foo, foo.bar, and foo.bar.baz imported,
foo.bar.baz bound as fbb
from foo.bar import baz # foo, foo.bar, and foo.bar.baz imported,
foo.bar.baz bound as baz
from foo import attr # foo imported and foo.attr bound as attr
```

如果标识符列表改为一个星号 (`'*'`),则在模块中定义的全部公有名称都将按
[`import`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#import) 语句
所在的作用域被绑定到局部命名空间。

一个模块所定义的 *公有名称* 是由在模块的命名空间中检测一个名为 `__all__` 的变量来确定的;如果有定


义,它必须是一个字符串列表,其中的项为该模块所定义或导入的名称。 在 `__all__` 中所给出的名称都会
被视为公有并且应当存在。 如果 `__all__` 没有被定义,则公有名称的集合将包含在模块的命名空间中找到
的所有不以下划线字符 (`'_'`) 打头的名称。 `__all__` 应当包括整个公有 API。 它的目标是避免意外地
导出不属于 API 的一部分的项(例如在模块内部被导入和使用的库模块)。

通配符形式的导入 --- `from module import *` --- 仅在模块层级上被允许。 尝试在类或函数定义中使


用它将引发
[`SyntaxError`](https://docs.python.org/zh-cn/3/library/exceptions.html#SyntaxError
)。

当指定要导入哪个模块时,你不必指定模块的绝对名称。 当一个模块或包被包含在另一个包之中时,可以在同一
个最高层级包中进行相对导入,而不必提及包名称。 通过在 [`from`](https://docs.python.org/zh-
cn/3/reference/simple_stmts.html#from) 之后指定的模块或包中使用前缀点号,你可以在不指定确切
名称的情况下指明在当前包层级结构中要上溯多少级。 一个前缀点号表示是执行导入的模块所在的当前包,两个
点号表示上溯一个包层级。 三个点号表示上溯两级,依此类推。 因此如果你执行 `from . import mod` 时
所处位置为 `pkg` 包内的一个模块,则最终你将导入 `pkg.mod`。 如果你执行 `from ..subpkg2
import mod` 时所处位置为 `pkg.subpkg1` 则你将导入 `pkg.subpkg2.mod`。 有关相对导入的规范说
明包含在 [包相对导
入](https://docs.python.org/zh-cn/3/reference/import.html#relativeimports) 一节中。

### future 语句
*future 语句* 是一种针对编译器的指令,指明某个特定模块应当使用在特定的未来某个 Python 发行版中成
为标准特性的语法或语义。

future 语句的目的是使得向在语言中引入了不兼容改变的 Python 未来版本的迁移更为容易。 它允许基于每


个模块在某种新特性成为标准之前的发行版中使用该特性。

```
future_stmt ::= "from" "__future__" "import" feature ["as" identifier]
("," feature ["as" identifier])*
| "from" "__future__" "import" "(" feature ["as" identifier]
("," feature ["as" identifier])* [","] ")"
feature ::= identifier
```

future 语句必须在靠近模块开头的位置出现。 可以出现在 future 语句之前行只有:

- 模块的文档字符串(如果存在),
- 注释,
- 空行,以及
- 其他 future 语句。

唯一需要使用 future 语句的特性是 `标注`

### global 语句

```
global_stmt ::= "global" identifier ("," identifier)*
```

[`global`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#global) 语句
是作用于整个当前代码块的声明。 它意味着所列出的标识符将被解读为全局变量。 要给全局变量赋值不可能不
用到 `global` 关键字,不过自由变量也可以指向全局变量而不必声明为全局变量。

### nonlocal 语句

```
nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*
```

[`nonlocal`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#nonlocal)
语句会使得所列出的名称指向之前在最近的包含作用域中绑定的除全局变量以外的变量。 这种功能很重要,因为
绑定的默认行为是先搜索局部命名空间。 这个语句允许被封装的代码重新绑定局部作用域以外且非全局(模块)
作用域当中的变量。

与 [`global`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#global)
语句中列出的名称不同,[`nonlocal`](https://docs.python.org/zh-cn/3/reference/
simple_stmts.html#nonlocal) 语句中列出的名称必须指向之前存在于包含作用域之中的绑定(在这个应当
用来创建新绑定的作用域不能被无歧义地确定)。

[`nonlocal`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#nonlocal)
语句中列出的名称不得与之前存在于局部作用域中的绑定相冲突。
## 复合语句

复合语句是包含其它语句(语句组)的语句;它们会以某种方式影响或控制所包含其它语句的执行。 通常,复合
语句会跨越多行,虽然在某些简单形式下整个复合语句也可能包含于一行之内

[`if`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#if), [`while`]
(https://docs.python.org/zh-cn/3/reference/compound_stmts.html#while) 和 [`for`]
(https://docs.python.org/zh-cn/3/reference/compound_stmts.html#for) 语句用来实现传统的
控制流程构造。
[`try`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#try) 语句为一
组语句指定异常处理和/和清理代码,而
[`with`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#with) 语句允
许在一个代码块周围执行初始化和终结化代码。 函数和类定义在语法上也属于复合语句。

一条复合语句由一个或多个‘子句’组成。 一个子句则包含一个句头和一个‘句体’。 特定复合语句的子句头


都处于相同的缩进层级。 每个子句头以一个作为唯一标识的关键字开始并以一个冒号结束。 子句体是由一个子
句控制的一组语句。 子句体可以是在子句头的冒号之后与其同处一行的一条或由分号分隔的多条简单语句,或者
也可以是在其之后缩进的一行或多行语句。 只有后一种形式的子句体才能包含嵌套的复合语句

```
compound_stmt ::= if_stmt
| while_stmt
| for_stmt
| try_stmt
| with_stmt
| match_stmt
| funcdef
| classdef
| async_with_stmt
| async_for_stmt
| async_funcdef
suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
statement ::= stmt_list NEWLINE | compound_stmt
stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
```

### if 语句

```
if_stmt ::= "if" assignment_expression ":" suite
("elif" assignment_expression ":" suite)*
["else" ":" suite]
```

### while 语句

```
while_stmt ::= "while" assignment_expression ":" suite
["else" ":" suite]
```

这将重复地检验表达式,并且如果其值为真就执行第一个子句体;如果表达式值为假(这可能在第一次检验时就
发生)则如果 `else` 子句体存在就会被执行并终止循环。
第一个子句体中的
[`break`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#break) 语句在
执行时将终止循环且不执行 `else` 子句体。 第一个子句体中的
[`continue`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#continue)
语句在执行时将跳过子句体中的剩余部分并返回检验表达式。

### for 语句

[`for`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#for) 语句用于
对序列(例如字符串、元组或列表)或其他可迭代对象中的元素进行迭代:

```
for_stmt ::= "for" target_list "in" starred_list ":" suite
["else" ":" suite]
```

第一个子句体中的
[`break`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#break) 语句在
执行时将终止循环且不执行 `else` 子句体。 第一个子句体中的
[`continue`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#continue)
语句在执行时将跳过子句体中的剩余部分并转往下一项继续执行,或者在没有下一项时转往 `else` 子句执行。

### try 语句

The `try` statement specifies exception handlers and/or cleanup code for a group of
statements:

```
try_stmt ::= try1_stmt | try2_stmt | try3_stmt
try1_stmt ::= "try" ":" suite
("except" [expression ["as" identifier]] ":" suite)+
["else" ":" suite]
["finally" ":" suite]
try2_stmt ::= "try" ":" suite
("except" "*" expression ["as" identifier] ":" suite)+
["else" ":" suite]
["finally" ":" suite]
try3_stmt ::= "try" ":" suite
"finally" ":" suite
```

#### except clause

The `except` clause(s) specify one or more exception handlers.

```
except E as N:
foo
```

被转写为

```
except E as N:
try:
foo
finally:
del N
```

Before an `except` clause's suite is executed, the exception is stored in the


[`sys`](https://docs.python.org/zh-cn/3/library/sys.html#module-sys) module, where
it can be accessed from within the body of the `except` clause by calling
[`sys.exception()`](https://docs.python.org/zh-cn/3/library/sys.html#sys.exception)
. When leaving an exception handler, the exception stored in the
[`sys`](https://docs.python.org/zh-cn/3/library/sys.html#module-sys) module is
reset to its previous value:

#### except * clause

The `except*` clause(s) are used for handling


[`ExceptionGroup`](https://docs.python.org/zh-cn/3/library/exceptions.html#Exceptio
nGroup)s. The exception type for matching is interpreted as in the case of
[`except`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#except),
but in the case of exception groups we can have partial matches when the type
matches some of the exceptions in the group. This means that multiple `except*`
clauses can execute, each handling part of the exception group. Each clause
executes at most once and handles an exception group of all matching exceptions.
Each exception in the group is handled by at most one `except*` clause, the first
that matches it.

```python
try:
... raise ExceptionGroup("eg",
... [ValueError(1), TypeError(2), OSError(3), OSError(4)])
... except* TypeError as e:
... print(f'caught {type(e)} with nested {e.exceptions}')
... except* OSError as e:
... print(f'caught {type(e)} with nested {e.exceptions}')
...
caught <class 'ExceptionGroup'> with nested (TypeError(2),)
caught <class 'ExceptionGroup'> with nested (OSError(3), OSError(4))
+ Exception Group Traceback (most recent call last):
| File "<stdin>", line 2, in <module>
| ExceptionGroup: eg
+-+---------------- 1 ----------------
| ValueError: 1
+------------------------------------
```

```python
try:
... raise BlockingIOError
... except* BlockingIOError as e:
... print(repr(e))
...
ExceptionGroup('', (BlockingIOError()))
```

An `except*` clause must have a matching type, and this type cannot be a subclass
of
[`BaseExceptionGroup`](https://docs.python.org/zh-cn/3/library/exceptions.html#Base
ExceptionGroup). It is not possible to mix [`except`](https://docs.python.org/zh-
cn/3/reference/compound_stmts.html#except) and `except*` in the same [`try`]
(https://docs.python.org/zh-cn/3/reference/compound_stmts.html#try). [`break`]
(https://docs.python.org/zh-cn/3/reference/simple_stmts.html#break), [`continue`]
(https://docs.python.org/zh-cn/3/reference/simple_stmts.html#continue) and
[`return`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#return)
cannot appear in an `except*` clause.

#### else clause

如果控制流离开
[`try`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#try) 子句体时
没有引发异常,并且没有执行
[`return`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#return),
[`continue`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#continue)
或 [`break`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#break) 语句,
可选的 `else` 子句将被执行。 `else` 语句中的异常不会由之前的
[`except`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#except) 子
句处理。

#### finally clause

If `finally` is present, it specifies a 'cleanup' handler.The


[`try`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#try) clause
is executed, including any
[`except`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#except)
and [`else`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#else)
clauses. If an exception occurs in any of the clauses and is not handled, the
exception is temporarily saved. The `finally` clause is executed. If there is a
saved exception it is re-raised at the end of the `finally` clause. If the
`finally` clause raises another exception, the saved exception is set as the
context of the new exception. If the `finally` clause executes a [`return`]
(https://docs.python.org/zh-cn/3/reference/simple_stmts.html#return), [`break`]
(https://docs.python.org/zh-cn/3/reference/simple_stmts.html#break) or [`continue`]
(https://docs.python.org/zh-cn/3/reference/simple_stmts.html#continue) statement,
the saved exception is discarded:

### with 语句

[`with`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#with) 语句用
于包装带有使用上下文管理器 (参见 [with 语句上下文管理
器](https://docs.python.org/zh-cn/3/reference/datamodel.html#context-managers) 一节)
定义的方法的代码块的执行。 这允许对普通的
[`try`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#try)...
[`except`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#except)...
[`finally`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#finally)
使用模式进行封装以方便地重用。

```
with_stmt ::= "with" ( "(" with_stmt_contents ","? ")" |
with_stmt_contents ) ":" suite
with_stmt_contents ::= with_item ("," with_item)*
with_item ::= expression ["as" target]
```

[`with`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#with) 语句的
执行过程:
1. 对上下文表达式(在
[`with_item`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#grammar
-token-python-grammar-with_item) 中给出的表达式)进行求值来获得上下文管理器。

2. 载入上下文管理器的 `__enter__()` 以便后续使用。

3. 载入上下文管理器的 `__exit__()` 以便后续使用。

4. 发起调用上下文管理器的 `__enter__()` 方法。

5. 如果
[`with`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#with) 语句中
包含一个目标,来自 `__enter__()` 的返回值将被赋值给它。

6. 执行语句体。

7. 发起调用上下文管理器的 `__exit__()` 方法。 如果语句体的退出是由异常导致的,则其类型、值和回溯


信息将被作为参数传递给 `__exit__()`。 否则的话,将提供三个
[`None`](https://docs.python.org/zh-cn/3/library/constants.html#None) 参数。

如果语句体的退出是由异常导致的,并且来自 `__exit__()` 方法的返回值为假,则该异常会被重新引发。


如果返回值为真,则该异常会被抑制,并会继续执行
[`with`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#with) 语句之
后的语句。

如果语句体由于异常以外的任何原因退出,则来自 `__exit__()` 的返回值会被忽略,并会在该类退出正


常的发生位置继续执行。

以下代码:

```
with EXPRESSION as TARGET:
SUITE
```

在语义上等价于:

```
manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False

try:
TARGET = value
SUITE
except:
hit_except = True
if not exit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
exit(manager, None, None, None)
```

如果有多个项目,则会视作存在多个
[`with`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#with) 语句嵌
套来处理多个上下文管理器:

```
with A() as a, B() as b:
SUITE
```

在语义上等价于:

```
with A() as a:
with B() as b:
SUITE
```

也可以用圆括号包围的多行形式的多项目上下文管理器。例如:

```
with (
A() as a,
B() as b,
):
SUITE
```

### match 语句

匹配语句用于进行模式匹配。语法如下:

```
match_stmt ::= 'match' subject_expr ":" NEWLINE INDENT case_block+ DEDENT
subject_expr ::= star_named_expression "," star_named_expressions?
| named_expression
case_block ::= 'case' patterns [guard] ":" block
```

模式匹配接受一个模式作为输入(跟在 `case` 后),一个目标值(跟在 `match` 后)。该模式(可能包含


子模式)将与目标值进行匹配。输出是:

- 匹配成功或失败(也被称为模式成功或失败)。
- 可能将匹配的值绑定到一个名字上。 这方面的先决条件将在下面进一步讨论。

#### 概述

示例:

```
flag = False
>>> match (100, 200):
... case (100, 300): # Mismatch: 200 != 300
... print('Case 1')
... case (100, 200) if flag: # Successful match, but guard fails
... print('Case 2')
... case (100, y): # Matches and binds y to 200
... print(f'Case 3, y: {y}')
... case _: # Pattern not attempted
... print('Case 4, I match anything!')
...
Case 3, y: 200
```

#### 约束项

```
guard ::= "if" named_expression
```

`guard` (它是 `case` 的一部分) 必须成立才能让 `case` 语句块中的代码被执行。 它所采用的形式为:


[`if`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#if) 之后跟一个表
达式。

拥有 `guard` 的 `case` 块的逻辑流程如下:

1. 检查 `case` 块中的模式是否匹配成功。如果该模式匹配失败,则不对 `guard` 进行求值,检查下一个


`case` 块。
2. 如果该模式匹配成功,对 `guard` 求值。
- 如果 `guard` 求值为真,则选用该 case 块。
- 如果 `guard` 求值为假,则不选用该 case 块。
- 如果在对 `guard` 求值过程中引发了异常,则异常将被抛出。

允许约束项产生副作用,因为他们是表达式。约束项求值必须从第一个 case 块到最后一个 case 块依次逐个


进行,模式匹配失败的 case 块将被跳过。(也就是说,约束项求值必须按顺序进行。)一旦选用了一个 case
块,约束项求值必须由此终止。

#### 必定匹配的 case 块

必定匹配的 case 块是能匹配所有情况的 case 块。一个匹配语句最多可以有一个必定匹配的 case 块,而且


必须是最后一个。

只有以下模式是必定匹配的:

- 左侧模式是必定匹配的 [AS 模
式](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#as-patterns)
- 包含至少一个必定匹配模式的 [或模
式](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#or-patterns)
- [捕获模式](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#capture-
patterns)
- [通配符模
式](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#wildcard-
patterns)
- 括号内的必定匹配模式

#### 模式
`patterns` 的顶层语法是:

```
patterns ::= open_sequence_pattern | pattern
pattern ::= as_pattern | or_pattern
closed_pattern ::= | literal_pattern
| capture_pattern
| wildcard_pattern
| value_pattern
| group_pattern
| sequence_pattern
| mapping_pattern
| class_pattern
```

- 或模式

或模式是由竖杠 `|` 分隔的两个或更多的模式。语法:

```
or_pattern ::= "|".closed_pattern+
```

- AS 模式

AS 模式将关键字
[`as`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#as) 左侧的或模式
与目标值进行匹配。语法:

```
as_pattern ::= or_pattern "as" capture_pattern
```

`P as NAME` 将与 `P` 匹配,成功后将设置 `NAME = <subject>` 。

- 字面值模式

字面值模式对应 Python 中的大多数 [字面


值](https://docs.python.org/zh-cn/3/reference/lexical_analysis.html#literals)。 语法
为:

```
literal_pattern ::= signed_number
| signed_number "+" NUMBER
| signed_number "-" NUMBER
| strings
| "None"
| "True"
| "False"
| signed_number: NUMBER | "-" NUMBER
```

规则 `strings` 和标记 `NUMBER` 是在 [standard Python


grammar](https://docs.python.org/zh-cn/3/reference/grammar.html) 中定义的。支持三引号
的字符串。不支持原始字符串和字节字符串。也不支持 [格式字符串字面
值](https://docs.python.org/zh-cn/3/reference/lexical_analysis.html#f-strings) 。

`signed_number '+' NUMBER` 和 `signed_number '-' NUMBER` 形式是用于表示 [复数]


(https://docs.python.org/zh-cn/3/reference/lexical_analysis.html#imaginary);它们要
求左边是一个实数而右边是一个虚数。 例如 `3 + 4j`。

简而言之, `LITERAL` 只会在 `<subject> == LITERAL` 时匹配成功。对于单例 `None` 、 `True`


和 `False` ,会使用
[`is`](https://docs.python.org/zh-cn/3/reference/expressions.html#is) 运算符

- 捕获模式

捕获模式将目标值与一个名称绑定。语法:

```
capture_pattern ::= !'_' NAME
```

```
NAME` 总是会匹配成功且将设置 `NAME = <subject>
```

- 通配符模式

通配符模式总是会匹配成功(匹配任何内容)并且不绑定任何名称。语法:

```
wildcard_pattern ::= '_'
```

`_` 总是会匹配成功

- 值模式

值模式代表 Python 中具有名称的值。语法:

```
value_pattern ::= attr
attr ::= name_or_attr "." NAME
name_or_attr ::= attr | NAME
```

模式中带点的名称会使用标准的 Python [名称解析规


则](https://docs.python.org/zh-cn/3/reference/executionmodel.html#resolve-names) 来
查找。 如果找到的值与目标值比较结果相等则模式匹配成功(使用 `==` 相等运算符)。

简而言之, `NAME1.NAME2` 仅在 `<subject> == NAME1.NAME2` 时匹配成功。

- 组模式

组模式允许用户在模式周围添加括号,以强调预期的分组。 除此之外,它没有额外的语法。语法:

```
group_pattern ::= "(" pattern ")"
```

简单来说 `(P)` 具有与 `P` 相同的效果。

- 序列模式

一个序列模式包含数个将与序列元素进行匹配的子模式

`[P1, P2, P3,` ... `, P<N>]` 仅在满足以下情况时匹配成功:

- 检查 `<subject>` 是一个序列
- `len(subject) == <N>`
- 将 `P1` 与 `<subject>[0]` 进行匹配(请注意此匹配可以绑定名称)
- 将 `P2` 与 `<subject>[1]` 进行匹配(请注意此匹配可以绑定名称)
- …… 剩余对应的模式/元素也以此类推。

- 映射模式

映射模式包含一个或多个键值模式。

`{KEY1: P1, KEY2: P2, ... }` 仅在满足以下情况时匹配成功:

- 检查 `<subject>` 是映射
- `KEY1 in <subject>`
- `P1` 与 `<subject>[KEY1]` 相匹配
- …… 剩余对应的键/模式对也以此类推

- 类模式

类模式表示一个类以及它的位置参数和关键字参数(如果有的话)。语法:

```
class_pattern ::= name_or_attr "(" [pattern_arguments ","?] ")"
pattern_arguments ::= positional_patterns ["," keyword_patterns]
| keyword_patterns
positional_patterns ::= ",".pattern+
keyword_patterns ::= ",".keyword_pattern+
keyword_pattern ::= NAME "=" pattern
```

`CLS(P1, attr=P2)` 仅在满足以下情况时匹配成功:

- `isinstance(<subject>, CLS)`

- 用 `CLS.__match_args__` 将 `P1` 转换为关键词模式

- - 对于每个关键词参数 `attr=P2` :

`hasattr(<subject>, "attr")`将 `P2` 与 `<subject>.attr` 进行匹配

- …… 剩余对应的关键字参数/模式对也以此类推
### 函数定义

函数定义就是对用户自定义函数的定义

```
funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")"
["->" expression] ":" suite
decorators ::= decorator+
decorator ::= "@" assignment_expression NEWLINE
parameter_list ::= defparameter ("," defparameter)* "," "/" [","
[parameter_list_no_posonly]]
| parameter_list_no_posonly
parameter_list_no_posonly ::= defparameter ("," defparameter)* [","
[parameter_list_starargs]]
| parameter_list_starargs
parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**"
parameter [","]]]
| "**" parameter [","]
parameter ::= identifier [":" expression]
defparameter ::= parameter ["=" expression]
funcname ::= identifier
```

函数定义是一条可执行语句。 它执行时会在当前局部命名空间中将函数名称绑定到一个函数对象(函数可执行代
码的包装器)。 这个函数对象包含对当前全局命名空间的引用,作为函数被调用时所使用的全局命名空间。

函数定义并不会执行函数体;只有当函数被调用时才会执行此操作。

一个函数定义可以被一个或多个
[decorator](https://docs.python.org/zh-cn/3/glossary.html#term-decorator) 表达式所包
装。 当函数被定义时将在包含该函数定义的作用域中对装饰器表达式求值。 求值结果必须是一个可调用对象,
它会以该函数对象作为唯一参数被发起调用。 其返回值将被绑定到函数名称而非函数对象。 多个装饰器会以嵌
套方式被应用。 例如以下代码

```
@f1(arg)
@f2
def func(): pass
```

大致等价于

```
def func(): pass
func = f1(arg)(f2(func))
```

在 "`/`" 之前的形参都是仅限位置形参因而只能通过位置参数传入

`: expression`: 任何形参都可以带有标注,表明参数的类型

`-> expression`:返回标注,表明返回值的类型

### 类定义
类定义就是对类对象的定义 (参见 [标准类型层级结
构](https://docs.python.org/zh-cn/3/reference/datamodel.html#types) 一节):

```
classdef ::= [decorators] "class" classname [inheritance] ":" suite
inheritance ::= "(" [argument_list] ")"
classname ::= identifier
```

类定义是一条可执行语句。 其中继承列表通常给出基类的列表 (进阶用法请参见 [元


类](https://docs.python.org/zh-cn/3/reference/datamodel.html#metaclasses)),列表中的
每一项都应当被求值为一个允许子类的类对象。 没有继承列表的类默认继承自基类
[`object`](https://docs.python.org/zh-cn/3/library/functions.html#object);因此,:

```
class Foo:
pass
```

等价于

```
class Foo(object):
pass
```

在类体内定义的属性的顺序保存在新类的 `__dict__` 中

类也可以被装饰

类定义内定义的变量是类属性;它们将被类实例所共享。 实例属性可通过 `self.name = value` 在方法中


设定。 类和实例属性均可通过 "`self.name`" 表示法来访问,当通过此方式访问时实例属性会隐藏同名的类
属性。 类属性可被用作实例属性的默认值,但在此场景下使用可变值可能导致未预期的结果。 可以使用 [描述
器](https://docs.python.org/zh-cn/3/reference/datamodel.html#descriptors) 来创建具有
不同实现细节的实例变量。

### 协程

#### 协程函数定义

```
async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")"
["->" expression] ":" suite
```

```
async def func(param1, param2):
do_stuff()
await some_coroutine()
```

#### async for 语句

```
async_for_stmt ::= "async" for_stmt
```

`async for` 语句允许方便地对异步可迭代对象进行迭代。

以下代码:

```
async for TARGET in ITER:
SUITE
else:
SUITE2
```

```
async for TARGET in ITER:
SUITE
else:
SUITE2
```

在语义上等价于:

```
iter = (ITER)
iter = type(iter).__aiter__(iter)
running = True

while running:
try:
TARGET = await type(iter).__anext__(iter)
except StopAsyncIteration:
running = False
else:
SUITE
else:
SUITE2
```

#### async with 语句

```
async_with_stmt ::= "async" with_stmt
```

以下代码:

```
async with EXPRESSION as TARGET:
SUITE
```

在语义上等价于:

```
manager = (EXPRESSION)
aenter = type(manager).__aenter__
aexit = type(manager).__aexit__
value = await aenter(manager)
hit_except = False

try:
TARGET = value
SUITE
except:
hit_except = True
if not await aexit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
await aexit(manager, None, None, None)
```

## 顶级组件

Python 解释器可以从多种源获得输入:作为标准输入或程序参数传入的脚本,以交互方式键入的语句,导入的
模块源文件等等。 这一章将给出在这些情况下所用的语法。

### 完整的 python 程序

一个完整的 Python 程序会在最小初始化环境中被执行:所有内置和标准模块均为可用,但均处于未初始化状态,


只有 [`sys`](https://docs.python.org/zh-cn/3/library/sys.html#module-sys) (各种系统服
务), [`builtins`](https://docs.python.org/zh-cn/3/library/builtins.html#module-
builtins) (内置函数、异常以及 `None`) 和
[`__main__`](https://docs.python.org/zh-cn/3/library/__main__.html#module-__main__)
除外。 最后一个模块用于为完整程序的执行提供局部和全局命名空间。

### 文件输入

所有从非交互式文件读取的输入都具有相同的形式:

```
file_input ::= (NEWLINE | statement)*
```

此语法用于下列几种情况:

- 解析一个完整 Python 程序时(从文件或字符串);


- 解析一个模块时;
- 解析一个传递给
[`exec()`](https://docs.python.org/zh-cn/3/library/functions.html#exec) 函数的字符串

### 交互式输入

交互模式下的输入使用以下语法进行解析:

```
interactive_input ::= [stmt_list] NEWLINE | compound_stmt NEWLINE
```

请注意在交互模式下一条(最高层级)复合语句必须带有一个空行;这对于帮助解析器确定输入的结束是必须的。
### 表达式输入

[`eval()`](https://docs.python.org/zh-cn/3/library/functions.html#eval) 被用于表达式
输入。 它会忽略开头的空白。 传递给
[`eval()`](https://docs.python.org/zh-cn/3/library/functions.html#eval) 的字符串参数
必须具有以下形式:

```
eval_input ::= expression_list NEWLINE*
```

## 完整的语法规范

```
# PEG grammar for Python

# ========================= START OF THE GRAMMAR =========================

# General grammatical elements and rules:


#
# * Strings with double quotes (") denote SOFT KEYWORDS
# * Strings with single quotes (') denote KEYWORDS
# * Upper case names (NAME) denote tokens in the Grammar/Tokens file
# * Rule names starting with "invalid_" are used for specialized syntax errors
# - These rules are NOT used in the first pass of the parser.
# - Only if the first pass fails to parse, a second pass including the invalid
# rules will be executed.
# - If the parser fails in the second phase with a generic syntax error, the
# location of the generic failure of the first pass will be used (this avoids
# reporting incorrect locations due to the invalid rules).
# - The order of the alternatives involving invalid rules matter
# (like any rule in PEG).
#
# Grammar Syntax (see PEP 617 for more information):
#
# rule_name: expression
# Optionally, a type can be included right after the rule name, which
# specifies the return type of the C or Python function corresponding to the
# rule:
# rule_name[return_type]: expression
# If the return type is omitted, then a void * is returned in C and an Any in
# Python.
# e1 e2
# Match e1, then match e2.
# e1 | e2
# Match e1 or e2.
# The first alternative can also appear on the line after the rule name for
# formatting purposes. In that case, a | must be used before the first
# alternative, like so:
# rule_name[return_type]:
# | first_alt
# | second_alt
# ( e )
# Match e (allows also to use other operators in the group like '(e)*')
# [ e ] or e?
# Optionally match e.
# e*
# Match zero or more occurrences of e.
# e+
# Match one or more occurrences of e.
# s.e+
# Match one or more occurrences of e, separated by s. The generated parse tree
# does not include the separator. This is otherwise identical to (e (s e)*).
# &e
# Succeed if e can be parsed, without consuming any input.
# !e
# Fail if e can be parsed, without consuming any input.
# ~
# Commit to the current alternative, even if it fails to parse.
#

# STARTING RULES
# ==============

file: [statements] ENDMARKER


interactive: statement_newline
eval: expressions NEWLINE* ENDMARKER
func_type: '(' [type_expressions] ')' '->' expression NEWLINE* ENDMARKER
fstring: star_expressions

# GENERAL STATEMENTS
# ==================

statements: statement+

statement: compound_stmt | simple_stmts

statement_newline:
| compound_stmt NEWLINE
| simple_stmts
| NEWLINE
| ENDMARKER

simple_stmts:
| simple_stmt !';' NEWLINE # Not needed, there for speedup
| ';'.simple_stmt+ [';'] NEWLINE

# NOTE: assignment MUST precede expression, else parsing a simple assignment


# will throw a SyntaxError.
simple_stmt:
| assignment
| star_expressions
| return_stmt
| import_stmt
| raise_stmt
| 'pass'
| del_stmt
| yield_stmt
| assert_stmt
| 'break'
| 'continue'
| global_stmt
| nonlocal_stmt
compound_stmt:
| function_def
| if_stmt
| class_def
| with_stmt
| for_stmt
| try_stmt
| while_stmt
| match_stmt

# SIMPLE STATEMENTS
# =================

# NOTE: annotated_rhs may start with 'yield'; yield_expr must start with 'yield'
assignment:
| NAME ':' expression ['=' annotated_rhs ]
| ('(' single_target ')'
| single_subscript_attribute_target) ':' expression ['=' annotated_rhs ]
| (star_targets '=' )+ (yield_expr | star_expressions) !'=' [TYPE_COMMENT]
| single_target augassign ~ (yield_expr | star_expressions)

annotated_rhs: yield_expr | star_expressions

augassign:
| '+='
| '-='
| '*='
| '@='
| '/='
| '%='
| '&='
| '|='
| '^='
| '<<='
| '>>='
| '**='
| '//='

return_stmt:
| 'return' [star_expressions]

raise_stmt:
| 'raise' expression ['from' expression ]
| 'raise'

global_stmt: 'global' ','.NAME+

nonlocal_stmt: 'nonlocal' ','.NAME+

del_stmt:
| 'del' del_targets &(';' | NEWLINE)

yield_stmt: yield_expr

assert_stmt: 'assert' expression [',' expression ]

import_stmt: import_name | import_from

# Import statements
# -----------------

import_name: 'import' dotted_as_names


# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
import_from:
| 'from' ('.' | '...')* dotted_name 'import' import_from_targets
| 'from' ('.' | '...')+ 'import' import_from_targets
import_from_targets:
| '(' import_from_as_names [','] ')'
| import_from_as_names !','
| '*'
import_from_as_names:
| ','.import_from_as_name+
import_from_as_name:
| NAME ['as' NAME ]
dotted_as_names:
| ','.dotted_as_name+
dotted_as_name:
| dotted_name ['as' NAME ]
dotted_name:
| dotted_name '.' NAME
| NAME

# COMPOUND STATEMENTS
# ===================

# Common elements
# ---------------

block:
| NEWLINE INDENT statements DEDENT
| simple_stmts

decorators: ('@' named_expression NEWLINE )+

# Class definitions
# -----------------

class_def:
| decorators class_def_raw
| class_def_raw

class_def_raw:
| 'class' NAME ['(' [arguments] ')' ] ':' block

# Function definitions
# --------------------

function_def:
| decorators function_def_raw
| function_def_raw

function_def_raw:
| 'def' NAME '(' [params] ')' ['->' expression ] ':' [func_type_comment] block
| ASYNC 'def' NAME '(' [params] ')' ['->' expression ] ':' [func_type_comment]
block

# Function parameters
# -------------------
params:
| parameters

parameters:
| slash_no_default param_no_default* param_with_default* [star_etc]
| slash_with_default param_with_default* [star_etc]
| param_no_default+ param_with_default* [star_etc]
| param_with_default+ [star_etc]
| star_etc

# Some duplication here because we can't write (',' | &')'),


# which is because we don't support empty alternatives (yet).

slash_no_default:
| param_no_default+ '/' ','
| param_no_default+ '/' &')'
slash_with_default:
| param_no_default* param_with_default+ '/' ','
| param_no_default* param_with_default+ '/' &')'

star_etc:
| '*' param_no_default param_maybe_default* [kwds]
| '*' param_no_default_star_annotation param_maybe_default* [kwds]
| '*' ',' param_maybe_default+ [kwds]
| kwds

kwds:
| '**' param_no_default

# One parameter. This *includes* a following comma and type comment.


#
# There are three styles:
# - No default
# - With default
# - Maybe with default
#
# There are two alternative forms of each, to deal with type comments:
# - Ends in a comma followed by an optional type comment
# - No comma, optional type comment, must be followed by close paren
# The latter form is for a final parameter without trailing comma.
#

param_no_default:
| param ',' TYPE_COMMENT?
| param TYPE_COMMENT? &')'
param_no_default_star_annotation:
| param_star_annotation ',' TYPE_COMMENT?
| param_star_annotation TYPE_COMMENT? &')'
param_with_default:
| param default ',' TYPE_COMMENT?
| param default TYPE_COMMENT? &')'
param_maybe_default:
| param default? ',' TYPE_COMMENT?
| param default? TYPE_COMMENT? &')'
param: NAME annotation?
param_star_annotation: NAME star_annotation
annotation: ':' expression
star_annotation: ':' star_expression
default: '=' expression | invalid_default

# If statement
# ------------

if_stmt:
| 'if' named_expression ':' block elif_stmt
| 'if' named_expression ':' block [else_block]
elif_stmt:
| 'elif' named_expression ':' block elif_stmt
| 'elif' named_expression ':' block [else_block]
else_block:
| 'else' ':' block

# While statement
# ---------------

while_stmt:
| 'while' named_expression ':' block [else_block]

# For statement
# -------------

for_stmt:
| 'for' star_targets 'in' ~ star_expressions ':' [TYPE_COMMENT] block
[else_block]
| ASYNC 'for' star_targets 'in' ~ star_expressions ':' [TYPE_COMMENT] block
[else_block]

# With statement
# --------------

with_stmt:
| 'with' '(' ','.with_item+ ','? ')' ':' block
| 'with' ','.with_item+ ':' [TYPE_COMMENT] block
| ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block
| ASYNC 'with' ','.with_item+ ':' [TYPE_COMMENT] block

with_item:
| expression 'as' star_target &(',' | ')' | ':')
| expression

# Try statement
# -------------

try_stmt:
| 'try' ':' block finally_block
| 'try' ':' block except_block+ [else_block] [finally_block]
| 'try' ':' block except_star_block+ [else_block] [finally_block]

# Except statement
# ----------------

except_block:
| 'except' expression ['as' NAME ] ':' block
| 'except' ':' block
except_star_block:
| 'except' '*' expression ['as' NAME ] ':' block
finally_block:
| 'finally' ':' block

# Match statement
# ---------------

match_stmt:
| "match" subject_expr ':' NEWLINE INDENT case_block+ DEDENT

subject_expr:
| star_named_expression ',' star_named_expressions?
| named_expression

case_block:
| "case" patterns guard? ':' block

guard: 'if' named_expression

patterns:
| open_sequence_pattern
| pattern

pattern:
| as_pattern
| or_pattern

as_pattern:
| or_pattern 'as' pattern_capture_target

or_pattern:
| '|'.closed_pattern+

closed_pattern:
| literal_pattern
| capture_pattern
| wildcard_pattern
| value_pattern
| group_pattern
| sequence_pattern
| mapping_pattern
| class_pattern

# Literal patterns are used for equality and identity constraints


literal_pattern:
| signed_number !('+' | '-')
| complex_number
| strings
| 'None'
| 'True'
| 'False'

# Literal expressions are used to restrict permitted mapping pattern keys


literal_expr:
| signed_number !('+' | '-')
| complex_number
| strings
| 'None'
| 'True'
| 'False'
complex_number:
| signed_real_number '+' imaginary_number
| signed_real_number '-' imaginary_number

signed_number:
| NUMBER
| '-' NUMBER

signed_real_number:
| real_number
| '-' real_number

real_number:
| NUMBER

imaginary_number:
| NUMBER

capture_pattern:
| pattern_capture_target

pattern_capture_target:
| !"_" NAME !('.' | '(' | '=')

wildcard_pattern:
| "_"

value_pattern:
| attr !('.' | '(' | '=')

attr:
| name_or_attr '.' NAME

name_or_attr:
| attr
| NAME

group_pattern:
| '(' pattern ')'

sequence_pattern:
| '[' maybe_sequence_pattern? ']'
| '(' open_sequence_pattern? ')'

open_sequence_pattern:
| maybe_star_pattern ',' maybe_sequence_pattern?

maybe_sequence_pattern:
| ','.maybe_star_pattern+ ','?

maybe_star_pattern:
| star_pattern
| pattern

star_pattern:
| '*' pattern_capture_target
| '*' wildcard_pattern
mapping_pattern:
| '{' '}'
| '{' double_star_pattern ','? '}'
| '{' items_pattern ',' double_star_pattern ','? '}'
| '{' items_pattern ','? '}'

items_pattern:
| ','.key_value_pattern+

key_value_pattern:
| (literal_expr | attr) ':' pattern

double_star_pattern:
| '**' pattern_capture_target

class_pattern:
| name_or_attr '(' ')'
| name_or_attr '(' positional_patterns ','? ')'
| name_or_attr '(' keyword_patterns ','? ')'
| name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')'

positional_patterns:
| ','.pattern+

keyword_patterns:
| ','.keyword_pattern+

keyword_pattern:
| NAME '=' pattern

# EXPRESSIONS
# -----------

expressions:
| expression (',' expression )+ [',']
| expression ','
| expression

expression:
| disjunction 'if' disjunction 'else' expression
| disjunction
| lambdef

yield_expr:
| 'yield' 'from' expression
| 'yield' [star_expressions]

star_expressions:
| star_expression (',' star_expression )+ [',']
| star_expression ','
| star_expression

star_expression:
| '*' bitwise_or
| expression

star_named_expressions: ','.star_named_expression+ [',']

star_named_expression:
| '*' bitwise_or
| named_expression

assignment_expression:
| NAME ':=' ~ expression

named_expression:
| assignment_expression
| expression !':='

disjunction:
| conjunction ('or' conjunction )+
| conjunction

conjunction:
| inversion ('and' inversion )+
| inversion

inversion:
| 'not' inversion
| comparison

# Comparison operators
# --------------------

comparison:
| bitwise_or compare_op_bitwise_or_pair+
| bitwise_or

compare_op_bitwise_or_pair:
| eq_bitwise_or
| noteq_bitwise_or
| lte_bitwise_or
| lt_bitwise_or
| gte_bitwise_or
| gt_bitwise_or
| notin_bitwise_or
| in_bitwise_or
| isnot_bitwise_or
| is_bitwise_or

eq_bitwise_or: '==' bitwise_or


noteq_bitwise_or:
| ('!=' ) bitwise_or
lte_bitwise_or: '<=' bitwise_or
lt_bitwise_or: '<' bitwise_or
gte_bitwise_or: '>=' bitwise_or
gt_bitwise_or: '>' bitwise_or
notin_bitwise_or: 'not' 'in' bitwise_or
in_bitwise_or: 'in' bitwise_or
isnot_bitwise_or: 'is' 'not' bitwise_or
is_bitwise_or: 'is' bitwise_or

# Bitwise operators
# -----------------

bitwise_or:
| bitwise_or '|' bitwise_xor
| bitwise_xor
bitwise_xor:
| bitwise_xor '^' bitwise_and
| bitwise_and

bitwise_and:
| bitwise_and '&' shift_expr
| shift_expr

shift_expr:
| shift_expr '<<' sum
| shift_expr '>>' sum
| sum

# Arithmetic operators
# --------------------

sum:
| sum '+' term
| sum '-' term
| term

term:
| term '*' factor
| term '/' factor
| term '//' factor
| term '%' factor
| term '@' factor
| factor

factor:
| '+' factor
| '-' factor
| '~' factor
| power

power:
| await_primary '**' factor
| await_primary

# Primary elements
# ----------------

# Primary elements are things like "obj.something.something", "obj[something]",


"obj(something)", "obj" ...

await_primary:
| AWAIT primary
| primary

primary:
| primary '.' NAME
| primary genexp
| primary '(' [arguments] ')'
| primary '[' slices ']'
| atom

slices:
| slice !','
| ','.(slice | starred_expression)+ [',']

slice:
| [expression] ':' [expression] [':' [expression] ]
| named_expression

atom:
| NAME
| 'True'
| 'False'
| 'None'
| strings
| NUMBER
| (tuple | group | genexp)
| (list | listcomp)
| (dict | set | dictcomp | setcomp)
| '...'

group:
| '(' (yield_expr | named_expression) ')'

# Lambda functions
# ----------------

lambdef:
| 'lambda' [lambda_params] ':' expression

lambda_params:
| lambda_parameters

# lambda_parameters etc. duplicates parameters but without annotations


# or type comments, and if there's no comma after a parameter, we expect
# a colon, not a close parenthesis. (For more, see parameters above.)
#
lambda_parameters:
| lambda_slash_no_default lambda_param_no_default* lambda_param_with_default*
[lambda_star_etc]
| lambda_slash_with_default lambda_param_with_default* [lambda_star_etc]
| lambda_param_no_default+ lambda_param_with_default* [lambda_star_etc]
| lambda_param_with_default+ [lambda_star_etc]
| lambda_star_etc

lambda_slash_no_default:
| lambda_param_no_default+ '/' ','
| lambda_param_no_default+ '/' &':'

lambda_slash_with_default:
| lambda_param_no_default* lambda_param_with_default+ '/' ','
| lambda_param_no_default* lambda_param_with_default+ '/' &':'

lambda_star_etc:
| '*' lambda_param_no_default lambda_param_maybe_default* [lambda_kwds]
| '*' ',' lambda_param_maybe_default+ [lambda_kwds]
| lambda_kwds

lambda_kwds:
| '**' lambda_param_no_default

lambda_param_no_default:
| lambda_param ','
| lambda_param &':'
lambda_param_with_default:
| lambda_param default ','
| lambda_param default &':'
lambda_param_maybe_default:
| lambda_param default? ','
| lambda_param default? &':'
lambda_param: NAME

# LITERALS
# ========

strings: STRING+

list:
| '[' [star_named_expressions] ']'

tuple:
| '(' [star_named_expression ',' [star_named_expressions] ] ')'

set: '{' star_named_expressions '}'

# Dicts
# -----

dict:
| '{' [double_starred_kvpairs] '}'

double_starred_kvpairs: ','.double_starred_kvpair+ [',']

double_starred_kvpair:
| '**' bitwise_or
| kvpair

kvpair: expression ':' expression

# Comprehensions & Generators


# ---------------------------

for_if_clauses:
| for_if_clause+

for_if_clause:
| ASYNC 'for' star_targets 'in' ~ disjunction ('if' disjunction )*
| 'for' star_targets 'in' ~ disjunction ('if' disjunction )*

listcomp:
| '[' named_expression for_if_clauses ']'

setcomp:
| '{' named_expression for_if_clauses '}'

genexp:
| '(' ( assignment_expression | expression !':=') for_if_clauses ')'

dictcomp:
| '{' kvpair for_if_clauses '}'
# FUNCTION CALL ARGUMENTS
# =======================

arguments:
| args [','] &')'

args:
| ','.(starred_expression | ( assignment_expression | expression !':=') !'=')+
[',' kwargs ]
| kwargs

kwargs:
| ','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+
| ','.kwarg_or_starred+
| ','.kwarg_or_double_starred+

starred_expression:
| '*' expression

kwarg_or_starred:
| NAME '=' expression
| starred_expression

kwarg_or_double_starred:
| NAME '=' expression
| '**' expression

# ASSIGNMENT TARGETS
# ==================

# Generic targets
# ---------------

# NOTE: star_targets may contain *bitwise_or, targets may not.


star_targets:
| star_target !','
| star_target (',' star_target )* [',']

star_targets_list_seq: ','.star_target+ [',']

star_targets_tuple_seq:
| star_target (',' star_target )+ [',']
| star_target ','

star_target:
| '*' (!'*' star_target)
| target_with_star_atom

target_with_star_atom:
| t_primary '.' NAME !t_lookahead
| t_primary '[' slices ']' !t_lookahead
| star_atom

star_atom:
| NAME
| '(' target_with_star_atom ')'
| '(' [star_targets_tuple_seq] ')'
| '[' [star_targets_list_seq] ']'
single_target:
| single_subscript_attribute_target
| NAME
| '(' single_target ')'

single_subscript_attribute_target:
| t_primary '.' NAME !t_lookahead
| t_primary '[' slices ']' !t_lookahead

t_primary:
| t_primary '.' NAME &t_lookahead
| t_primary '[' slices ']' &t_lookahead
| t_primary genexp &t_lookahead
| t_primary '(' [arguments] ')' &t_lookahead
| atom &t_lookahead

t_lookahead: '(' | '[' | '.'

# Targets for del statements


# --------------------------

del_targets: ','.del_target+ [',']

del_target:
| t_primary '.' NAME !t_lookahead
| t_primary '[' slices ']' !t_lookahead
| del_t_atom

del_t_atom:
| NAME
| '(' del_target ')'
| '(' [del_targets] ')'
| '[' [del_targets] ']'

# TYPING ELEMENTS
# ---------------

# type_expressions allow */** but ignore them


type_expressions:
| ','.expression+ ',' '*' expression ',' '**' expression
| ','.expression+ ',' '*' expression
| ','.expression+ ',' '**' expression
| '*' expression ',' '**' expression
| '*' expression
| '**' expression
| ','.expression+

func_type_comment:
| NEWLINE TYPE_COMMENT &(NEWLINE INDENT) # Must be followed by indented block
| TYPE_COMMENT

# ========================= END OF THE GRAMMAR ===========================

# ========================= START OF INVALID RULES =======================


```

You might also like