# 流程控制
- Python 提供了以下几种语法,来控制程序的运行流程:
- 选择结构
- if
- match-case
- 循环结构
- for
- while
- 选择结构
# if
if 语句用于判断条件、选择分支,最简单的格式如下:
if condition: statement_block
- 如果 condition 条件表达式结果为 True ,则会执行 statement_block 语句块。否则,跳过 statement_block 。
- 例:
if 1 > 0: print('yes')
- 除了简单的比较运算,condition 还可以是 int、str、函数等形式。执行
if condition
相当于执行if bool(condition)
,总是会得到一个 True 或 False 值。
可选加上 else 语句,表示条件表达式为 False 时,执行什么操作。如下:
if condition: statement_block else: statement_block
可选加上任意个 elif 语句,从而依次判断多个条件表达式。如下:
if condition: statement_block elif condition: statement_block elif condition: statement_block
- 如果第一个 condition 结果为 False ,则检查第二个 condition 。如果第二个 condition 结果也为 False ,则检查第三个 condition ,以此类推。
- 如果所有 condition 结果都为 False ,则执行 else 语句下的 statement_block 。不过也可以省略 else 语句。
- 如果某个 condition 结果都为 True ,则执行对应的 statement_block ,并跳过后续所有 elif、else 。
- 注意 if、elif、else 语句的末尾,都要加上冒号
:
。
# match-case
match-case 语句用于模式匹配。格式如下:
match <expression> case <pattern>: <block> case <pattern>: <block> ...
- 执行时,会从上到下依次将 expression 与每个 case pattern 比较。如果匹配,则执行该 case block ,并结束 match-case 语句块。
例:
match 1: case 1: # Literal Patterns :如果 pattern 为普通数据类型,则当 expression == pattern 时,视作匹配 pass case 1: # 允许声明重复的 case pattern pass case {1:''}: # Mapping Patterns :如果 pattern 为 dict 类型,则当 pattern 包含于 expression 时,视作匹配 print(1) case x: # Capture Patterns :如果 pattern 为一个标识符,则视作变量,会匹配一个任意值,并赋值(称为 bind )。该变量在 match-case 语句块之后依然存在 print(x) case 1 | 'A': # 可以用 | 连接多个 pattern ,分别尝试匹配 pass case [1, x, y] | (x, y): # 用 | 连接的每个 pattern 中,必须使用相同数量、名称的变量,否则抛出异常:SyntaxError: alternative patterns bind different names pass case 1 as x: # 可以用关键字 as 将匹配结果赋值给一个变量 print(x) case [1, (2 | 3) as x]: pass case [1, x] if x > 0: # 可以添加 if 条件。先判断 case pattern 是否匹配,如果匹配则绑定变量,再判断 if 条件是否成立,如果成立才执行 case block print(x) case [1, *args]: # 支持使用 * 元组参数,匹配任意个值 print(*args) case {1: _, **kwargs}: # pattern 为 dict 类型时,支持使用 ** 字典参数 print(kwargs) case _: # Wildcard Pattern :如果 pattern 只是一个 _ ,则可以匹配任意值,但不会绑定赋值给 _ 。如果 pattern 不止包含 _ ,则当作 Capture Patterns 处理 pass
Class Patterns :如果 pattern 为一个对象,则先比较 expression、pattern 是否属于同一 class ,再比较实参列表是否相同,如果相同才算匹配。
- pattern 不能是一个类名,否则会当作 Capture Patterns 处理。
>>> match 1: ... case str: # 这里会把 expression 赋值给标识符 str ... print(str) ... 1
- 内置类已经实现了
__match_args__
,可以直接匹配。>>> match 1: ... case int(1): ... print(1) ... 1
- 比较实参列表时,字典参数会直接比较,而位置参数会根据
__match_args__
转换成字典参数再比较。>>> class Point: ... __match_args__ = ('x', 'y') ... def __init__(self, x=0, y=0): ... self.x = x ... self.y = y ... >>> >>> match Point(): ... case Point(): ... print(1) ... 1 >>> match Point(1, 2): ... case Point(1, y=2): ... print(1) ... 1
__match_args__
取值为 tuple 类型。如果未定义,则在 case 比较时会抛出异常:TypeError: Point() accepts 0 positional sub-patterns (1 given)
- pattern 不能是一个类名,否则会当作 Capture Patterns 处理。
# for
C 语言中,for 语句的功能是,执行指定次数的循环。例如:
for(i; i<3; i++)
Python 语言中,for 语句的功能不同,是迭代(或者说遍历)一个对象中的所有元素。每获取一个元素,就执行一次 for 语句的循环体 statement_block 。
- 目标对象必须属于可迭代对象。
- 一般格式如下:
for item in iterable: statement_block
- 例:
for i in 'hello': print(i)
for _ in range(4): # 如果不想遍历对象,只想执行指定次数的循环,则可以用 range() 函数创建一个指定长度的迭代器 print('hello')
- 每次迭代得到的一个元素,如果也属于可迭代对象,则可以 unpack 拆开成 n 个值,同时赋值给 n 个变量。例:
>>> for x,y in ['ab', 'cd']: ... print(x,y) ... a b c d
如果目标对象,包含可执行代码(比如调用一个函数),则只会执行一次。例如:
>>> def fun1(): ... print('this is fun1()') ... return 'hi' ... >>> for i in fun1(): ... print(i) ... this is fun1() # 函数只执行了一次 h i
相当于:
_ = fun1() for i in _: print(i)
迭代的过程中,目标对象包含的元素不能变化,否则会引发异常:
>>> dic = {'k1': 1, 'k2': 2} >>> for k in dic.keys(): ... dic.pop(k) ... 1 RuntimeError: dictionary changed size during iteration >>> d {'k2': 10}
为了解决该问题,可以先快速迭代一次,暂存所有元素,然后才慢慢迭代:
>>> dic = {'k1': 1, 'k2': 2} >>> _ = list(dic.keys()) >>> for k in _: ... dic.pop(k) ... 1 2
# while
while 语句的功能是:只要满足指定条件,则反复执行一个循环。
- 一般格式如下:
while condition: statement_block
- 运行流程:第一步,检查 condition 的值,
- 如果为 True ,则执行一遍 statement_block 。执行之后,回到第一步,再次检查 condition 的值。
- 如果为 False ,则结束 while 语句块。
- 一般格式如下:
Python 的 for、while 循环语句中,
- 可以用关键字 break ,立即结束当前的 for 或 while 循环。
- 可以用关键字 continue ,跳到下一次循环。
- 可以附加 else 语句块。如果 for 或 while 循环是正常结束的(因为不满足循环条件而结束),则会执行 else 语句块。如果提前结束循环(因为 break、抛出异常等原因),则不会执行 else 语句块。例:
>>> for i in range(3): ... print(i) ... else: ... print('else') ... 0 1 2 else