00 Python
00 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>类似,<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
```
- 缩进:逻辑行开头的空白符(空格符和制表符)用于计算该行的缩进层级,决定语句组块;缩进层级以堆栈形
式生成 INDENT 和 DEDENT 形符
- 关键字
```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
```
- 保留的标识符类
\_\_*\_\_:系统定义的名称,这些名称由解释器及其实现(包括标准库)定义
__*:类的私有名称
- 字符串及字节串字面值
```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 的类型,类型不可改变
可变对象:值可以改变,如:字典和列表
不可变对象:值不可以改变,如:数字,字符串和元组
对象绝不会显式销毁
### 标准类型层级结构
- None:空值,逻辑为假,无返回值函数返回 None
- NotImplemented:未实现指定运算时返回
- Ellipsis:...
- numbers.Number:数字,整数(整型和布尔型)numbers.Integral,浮点数(双精
度)numbers.Real,和复数 numbers.Complex
- 序列:此类对象表示以非负整数作为索引的有限有序集
不可变序列:字符串、元组、字节串
可变序列:列表,字节数组
- 集合:此类对象表示由不重复且不可变对象组成的无序且有限的集合
- 可调用类型:
用户定义函数:def
实例方法:
生成器函数:yield,用于迭代逐个获取
协程函数:async def
异步生成器函数:async def+yield
内置函数:C 函数的外部封装
内置方法:同【内置函数】
类:\_\_new\_\_
类实例:\_\_call\_\_
导入方式:import、importlib.import_module() 、\_\_import\_\_()
属性:\_\_name\_\_,\_\_doc\_\_,\_\_file\_\_,\_\_dict\_\_
- 自定义类:class
- 类实例:类实例可通过调用类对象来创建
sys.stdin,sys.stdout,sys.stderr 对应于解释器标准输入、输出和错误流的文件对象
- 内部类型:某些由解释器内部使用的类型也被暴露给用户
帧对象:帧对象表示执行帧
回溯对象:回溯对象表示一个异常的栈跟踪记录
切片对象:slice()创建
静态方法对象:staticmethod()创建
类方法对象:classmethod()创建
### 特殊方法名称
一个类可以通过定义具有特殊名称的方法来实现由特殊语法来发起调用的特定操作(例如算术运算或抽取与切
片);
可以理解为语法糖,使用特定语法时,编译器将编译成调用特定的对象中的特定方法
#### 基本定制
- `object.__del__(self)`:在实例将被销毁时调用。当解释器退出时不会确保为仍然存在的对象调用
`__del__()`方法。
- `object.__str__(self)`:生成一个对象的“非正式”或格式良好的字符串表示
- `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
#### 自定义属性访问
可以定义下列方法来自定义对类实例属性访问(x.name 的使用、赋值或删除)的具体含义
- `object.__getattribute__(self, name)`:此方法会无条件地被调用以实现对类实例属性的访问
- 描述器
`object.__delete__(self, instance)`
- `object.__slots__`:这个类变量可赋值为字符串、可迭代对象或由实例使用的变量名组成的字符串序列。
`__slots__` 会为已声明的变量保留空间并阻止自动为每个实例创建 `__dict__` 和 `__weakref__`。
- `classmethod object.__init_subclass__(cls)`:当所在类派生子类时此方法就会被调用。*cls*
将指向新的子类。如果定义为一个普通实例方法,此方法将被隐式地转换为类方法。
```python
class A:
x = C() # Automatically calls: x.__set_name__(A, 'x')
```
```python
class Meta(type):
pass
class MyClass(metaclass=Meta):
pass
class MySubclass(MyClass):
pass
```
当一个类定义被执行时,将发生以下步骤:
- 解析 MRO 条目
- 确定适当的元类
- 如果没有基类且没有显式指定元类,则使用 type()
- 如果给出一个显式元类而且 *不是* type()的实例,则其会被直接用作元类;
- 如果给出一个 type()的实例作为显式元类,或是定义了基类,则使用最近派生的元类。
- 准备类命名空间
- 执行类主体
- 创建类对象
#### 自定义实例及子类检查
#### 模拟泛型类型
#### 模拟可调用对象
- `object.__call__(self[, args...])`:此方法会在实例作为一个函数被“调用”时被调用;如果定义
了此方法,则 `x(arg1, arg2, ...)` 就大致可以被改写为 `type(x).__call__(x, arg1, ...)`。
#### 模拟容器对象
- `object.__len__(self)`:调用此方法以实现内置函数 len()
#### 模拟数字类型
- `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)
```
```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 语句
- `object.__enter__(self)`:进入与此对象相关的运行时上下文
- `object.__exit__(self, exc_type, exc_value, traceback)`:退出关联到此对象的运行时上下
文。 各个参数描述了导致上下文退出的异常。 如果上下文是无异常地退出的,三个参数都将为 None。
#### 定制类模式匹配中的位置参数
- `object.__match_args__`
#### 特殊方法查找
对于自定义类来说,特殊方法的隐式发起调用仅保证在其定义于对象类型中时能正确地发挥作用,而不能定义在
对象实例字典中
### 协程
#### 可等待对象
#### 协程对象
- `coroutine.send(value)`:开始或恢复协程的执行
- `coroutine.throw(value)`,`coroutine.throw(type[, value[, traceback]])`:在协程内引
发指定的异常
- `coroutine.close()`:此方法会使得协程清理自身并退出
#### 异步迭代器
- `object.__aiter__(self)`:必须返回一个 *异步迭代器* 对象
```python
class Reader:
async def readline(self):
...
def __aiter__(self):
return self
#### 异步上下文管理器
- `object.__aenter__(self)`:在语义上类似于 `__enter__()`,仅有的区别是它必须返回一个 可等
待对象
- `object.__aexit__(self, exc_type, exc_value, traceback)`:在语义上类似于
`__exit__()`,仅有的区别是它必须返回一个 可等待对象
## 执行模型
### 程序的结构
代码块在执行帧中被执行
### 命名与绑定
#### 名称的绑定
#### 名称的解析
#### 内置命名空间和受限的执行
与一个代码块的执行相关联的内置命名空间实际上是通过在其全局命名空间中搜索名称 `__builtins__` 来找
到的
#### 与动态特性的交互
自由变量的名称解析发生于运行时而不是编译时
### 异常
捕获:try...except...finally
## 导入系统
- import:它先搜索指定名称的模块,然后将搜索结果绑定到当前作用域中的名称;底层通过`__import__`
来实现
- `__import__`:直接调用将仅执行模块搜索以及在找到时的模块创建操作
- importlib.import_module():可能会选择绕过 `__import__()` 并使用它们自己的解决方案来实现导
入机制
#### importlib
#### 包
要注意的一个重点概念是所有包都是模块,但并非所有模块都是包。 或者换句话说,包只是一种特殊的模块。
特别地,任何具有 `__path__` 属性的模块都会被当作是包。
所有模块都有自己的名字。 子包名与其父包名会以点号分隔,如:email.mime.text
- 常规包
```python
parent/
__init__.py
one/
__init__.py
two/
__init__.py
three/
__init__.py
```
- 命名空间包
#### 搜索
- 模块缓存
sys.modules 是可写的
- 查找器和加载器
- 导入钩子
- 元路径
#### 加载
当一个模块说明被找到时,导入机制将在加载该模块时使用它(及其所包含的加载器)
- 加载器
模块加载器提供关键的加载功能:模块执行。导入机制调用 importlib.abc.Loader.exec_module() 方
法并传入一个参数来执行模块对象。 从 exec_module() 返回的任何值都将被忽略。
exec_module():执行模块
- 子模块
```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'>
```
- 模块规格说明
导入机制在导入期间会使用有关每个模块的多种信息,特别是加载之前。 大多数信息都是所有模块通用的。
模块规格说明的目的是基于每个模块来封装这些导入相关信息。
在导入期间使用规格说明可允许状态在导入系统各组件之间传递,例如在创建模块规格说明的查找器和执行模
块的加载器之间。 最重要的一点是,它允许导入机制执行加载的样板操作,在没有模块规格说明的情况下这是加
载器的责任。
- 导入相关的模块属性
`__name__`:【必须】模块的唯一标识名称
`__loader__`:【必须】被设为导入系统在加载模块时使用的加载器对象
`__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__`
- 模块的 repr
默认情况下,全部模块都具有一个可用的 repr,但是你可以依据上述的属性设置,在模块的规格说明中更为
显式地控制模块对象的 repr。
- 已缓存字节码的失效
#### 基于路径的查找器
- 路径条目查找器
- 路径条目查找器协议
为了支持模块和已初始化包的导入,也为了给命名空间包提供组成部分,路径条目查找器必须实现
find_spec() 方法。
#### 替换标准导入系统
一个可行的方式是仅改变导入语句的行为而不影响访问导入系统的其他 API,那么替换内置的
`__import__()` 函数可能就够了。 这种技巧也可以在模块层级上运用,即只在某个模块内部改变导入语句的
行为。
想要选择性地预先防止在元路径上从一个钩子导入某些模块(而不是完全禁用标准导入系统),只需直接从
find_spec() 引发 ModuleNotFoundError 而非返回 None 就足够了。 返回后者表示元路径搜索应当继续,
而引发异常则会立即终止搜索。
#### 包相对导入
#### 有关`__main__`的特殊事项
## 表达式
### 算术转换
- 如果任一参数为复数,另一参数会被转换为复数;
- 否则,如果任一参数为浮点数,另一参数会被转换为浮点数;
- 否则,两者应该都为整数,不需要进行转换。
### 原子
```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) "}"
```
#### 字典显示
```
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_atom ::= "(" yield_expression ")"
yield_expression ::= "yield" [expression_list | "from" expression]
```
- 生成器-迭代器的方法
`generator.throw(value)`
`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.
```
- 异步生成器函数
- 异步生成器-迭代器方法
`coroutine agen.__anext__()`:返回一个可等待对象,它在运行时会开始执行该异步生成器或是从上
次执行的 yield 表达式位置恢复执行。此方法通常是通过 async for 循环隐式地调用。
`coroutine agen.asend(value)`:返回一个可等待对象,它在运行时会恢复该异步生成器的执行
`coroutine agen.athrow(value)`
`coroutine agen.aclose()`:返回一个可等待对象,它会在运行时向异步生成器函数暂停的位置抛入一
个 GeneratorExit。
### 原型
原型代表编程语言中最紧密绑定的操作。 它们的句法如下:
```
primary ::= atom | attributeref | subscription | slicing | call
```
#### 属性引用
属性引用是后面带有一个句点加一个名称的原型:
```
attributeref ::= primary "." identifier
```
产生过程可通过重载 `__getattr__()` 方法来自定义
#### 抽取
```
subscription ::= primary "[" expression_list "]"
```
#### 切片
```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
```
#### 调用
```
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` 句法,该正式参数将接受一个包含了多余关键字参数的字典
(使用关键字作为键而参数值作为与键对应的值),如果没有多余关键字参数则为一个(新的)空字典。
如果类型为---
- 用户自定义函数:
函数的代码块会被执行,并向其传入参数列表。 代码块所做的第一件事是将正式形参绑定到对应参数;相关描
述参见 [函数定
义](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)。
- 类对象:
返回该类的一个新实例。
- 类实例方法:
调用相应的用户自定义函数,向其传入的参数列表会比调用的参数列表多一项:该实例将成为第一个参数。
- 类实例:
挂起 [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
```
在所有三种情况下,如果参数的类型不正确,将引发 [`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
```
`x == (x//y)*y + (x%y)`
#### 移位运算
移位运算的优先级低于算术运算:
```
shift_expr ::= a_expr | shift_expr ("<<" | ">>") a_expr
```
这些运算符接受整数参数。 它们会将第一个参数左移或右移第二个参数所指定的比特位数。
#### 二元位运算
三种位运算具有各不相同的优先级:
```
and_expr ::= shift_expr | and_expr "&" shift_expr
xor_expr ::= and_expr | xor_expr "^" and_expr
or_expr ::= xor_expr | or_expr "|" xor_expr
```
#### 比较运算
```
comparison ::= or_expr (comp_operator or_expr)*
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="
| "is" ["not"] | ["not"] "in"
```
正式的说法是这样:如果 *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)`。
- 标识号比较
运算符 [`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
```
请注意 [`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
```
```
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
```
除了作为列表或集合显示的一部分,包含至少一个逗号的表达式列表将生成一个元组。 元组的长度就是列表中表
达式的数量。 表达式将从左至右被求值。
- 求值顺序
在以下几行中,表达式将按其后缀的算术优先顺序被求值。:
```
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]
```
```
if __debug__:
if not expression: raise AssertionError
```
```
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)
### 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) 在语
法上只会出现于函数定义所嵌套的代码,不会出现于类定义所嵌套的代码。
[`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) 来提示发生了错误
吃掉异常
```
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) 循环
所嵌套的代码,但不会出现于该循环内部的函数或类定义所嵌套的代码。
```
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 | "."+
```
1. 查找一个模块,如果有必要还会加载并初始化模块。
2. 在局部命名空间中为
[`import`](https://docs.python.org/zh-cn/3/reference/simple_stmts.html#import) 语句
发生位置所处的作用域定义一个或多个名称
如果成功获取到请求的模块,则可以通过以下三种方式一之在局部命名空间中使用它:
[`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
)。
```
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) 语句
所在的作用域被绑定到局部命名空间。
当指定要导入哪个模块时,你不必指定模块的绝对名称。 当一个模块或包被包含在另一个包之中时,可以在同一
个最高层级包中进行相对导入,而不必提及包名称。 通过在 [`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_stmt ::= "from" "__future__" "import" feature ["as" identifier]
("," feature ["as" identifier])*
| "from" "__future__" "import" "(" feature ["as" identifier]
("," feature ["as" identifier])* [","] ")"
feature ::= identifier
```
- 模块的文档字符串(如果存在),
- 注释,
- 空行,以及
- 其他 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 E as N:
foo
```
被转写为
```
except E as N:
try:
foo
finally:
del N
```
```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.
如果控制流离开
[`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) 子
句处理。
### 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) 中给出的表达式)进行求值来获得上下文管理器。
5. 如果
[`with`](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#with) 语句中
包含一个目标,来自 `__enter__()` 的返回值将被赋值给它。
6. 执行语句体。
以下代码:
```
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
```
- 匹配成功或失败(也被称为模式成功或失败)。
- 可能将匹配的值绑定到一个名字上。 这方面的先决条件将在下面进一步讨论。
#### 概述
示例:
```
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
```
只有以下模式是必定匹配的:
- 左侧模式是必定匹配的 [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
```
- 字面值模式
```
literal_pattern ::= signed_number
| signed_number "+" NUMBER
| signed_number "-" NUMBER
| strings
| "None"
| "True"
| "False"
| signed_number: NUMBER | "-" NUMBER
```
- 捕获模式
捕获模式将目标值与一个名称绑定。语法:
```
capture_pattern ::= !'_' NAME
```
```
NAME` 总是会匹配成功且将设置 `NAME = <subject>
```
- 通配符模式
通配符模式总是会匹配成功(匹配任何内容)并且不绑定任何名称。语法:
```
wildcard_pattern ::= '_'
```
`_` 总是会匹配成功
- 值模式
```
value_pattern ::= attr
attr ::= name_or_attr "." NAME
name_or_attr ::= attr | NAME
```
- 组模式
组模式允许用户在模式周围添加括号,以强调预期的分组。 除此之外,它没有额外的语法。语法:
```
group_pattern ::= "(" pattern ")"
```
- 序列模式
一个序列模式包含数个将与序列元素进行匹配的子模式
- 检查 `<subject>` 是一个序列
- `len(subject) == <N>`
- 将 `P1` 与 `<subject>[0]` 进行匹配(请注意此匹配可以绑定名称)
- 将 `P2` 与 `<subject>[1]` 进行匹配(请注意此匹配可以绑定名称)
- …… 剩余对应的模式/元素也以此类推。
- 映射模式
映射模式包含一个或多个键值模式。
- 检查 `<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
```
- `isinstance(<subject>, CLS)`
- - 对于每个关键词参数 `attr=P2` :
- …… 剩余对应的关键字参数/模式对也以此类推
### 函数定义
函数定义就是对用户自定义函数的定义
```
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
```
```
class Foo:
pass
```
等价于
```
class Foo(object):
pass
```
在类体内定义的属性的顺序保存在新类的 `__dict__` 中
类也可以被装饰
### 协程
#### 协程函数定义
```
async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")"
["->" expression] ":" suite
```
```
async def func(param1, param2):
do_stuff()
await some_coroutine()
```
```
async_for_stmt ::= "async" for_stmt
```
以下代码:
```
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_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 解释器可以从多种源获得输入:作为标准输入或程序参数传入的脚本,以交互方式键入的语句,导入的
模块源文件等等。 这一章将给出在这些情况下所用的语法。
### 文件输入
所有从非交互式文件读取的输入都具有相同的形式:
```
file_input ::= (NEWLINE | statement)*
```
此语法用于下列几种情况:
### 交互式输入
交互模式下的输入使用以下语法进行解析:
```
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
# STARTING RULES
# ==============
# GENERAL STATEMENTS
# ==================
statements: statement+
statement_newline:
| compound_stmt NEWLINE
| simple_stmts
| NEWLINE
| ENDMARKER
simple_stmts:
| simple_stmt !';' NEWLINE # Not needed, there for speedup
| ';'.simple_stmt+ [';'] NEWLINE
# 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)
augassign:
| '+='
| '-='
| '*='
| '@='
| '/='
| '%='
| '&='
| '|='
| '^='
| '<<='
| '>>='
| '**='
| '//='
return_stmt:
| 'return' [star_expressions]
raise_stmt:
| 'raise' expression ['from' expression ]
| 'raise'
del_stmt:
| 'del' del_targets &(';' | NEWLINE)
yield_stmt: yield_expr
# Import statements
# -----------------
# COMPOUND STATEMENTS
# ===================
# Common elements
# ---------------
block:
| NEWLINE INDENT statements DEDENT
| simple_stmts
# 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
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
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
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
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_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
# 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
# ----------------
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_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] ] ')'
# Dicts
# -----
dict:
| '{' [double_starred_kvpairs] '}'
double_starred_kvpair:
| '**' bitwise_or
| kvpair
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
# ---------------
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
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
# ---------------
func_type_comment:
| NEWLINE TYPE_COMMENT &(NEWLINE INDENT) # Must be followed by indented block
| TYPE_COMMENT