Python学习笔记——3.流程控制与异常
一些关于流程控制的语法,没什么好说的,各种语言都大同小异,直接给例子即可。
条件语句
if 条件
直接给例子,只需要注意一下用elif
而非else if
1 | if a==1: |
最简单的单行 if 也是可以的
1 | if True: print("hello") |
还可以使用如下的单行 if 表达式,类似于 C 语言的三目运算符,它算作表达式,因此也可以用在 lambda 表达式中
1 | result = 1 if True else -1 # 1 |
注意:在 if 中的条件可以包括与或非等更复杂的逻辑判断,但是只能使用
and or not
来代表,不支持
&& || !
;(C++对这两套都支持,但是主要使用后者)
match 匹配
Python 早期不支持 switch 语句,只能用 if 语句,较新的版本加上了与之类似的match语句。 match语句支持比C++的switch更复杂的逻辑,后者只能基于一个整数判断,前者甚至可以进行正则匹配,这里不做讨论。
例如 1
2
3
4
5
6
7
8
9
10def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _:
return "Something's wrong with the internet"
循环语句
Python的循环语句效率非常低,对运行效率有要求时应尽量避免使用,可以使用numpy提供的向量化操作、列表推导式等进行替代。
while 循环
直接给例子即可
1 | a=1 |
最简单的单行 while 也是可以的
1 | a=2 |
for 遍历
Python 的 for 语句只能基于一个可遍历的对象(列表,元组,字典等),因此称为 for 遍历比 for 循环更合适。
对于列表、元组和集合,for 循环可以获取其中的每一项
1 | words = ['a1','b1','c1'] |
对于字典,for 循环获取的是每一个键值对中的键,而不是对应的值!
1 | dict = {'a':1,'b':2} |
注意:
和 C++的迭代器一样,在过程中尝试修改遍历对象的行为是不可控的!如果需要修改,考虑遍历此对象的副本
1
2
3
4
5
6
7
8
9
10
11
12users = {'Hans': 'active', 'Éléonore': 'inactive', '景太郎': 'active'}
# 遍历副本,修改原对象
for user, status in users.copy().items():
if status == 'inactive':
del users[user]
# 遍历原对象,创建一个新对象
active_users = {}
for user, status in users.items():
if status == 'active':
active_users[user] = statufor 遍历语句中的临时变量并不会在退出遍历时被自动删除,而是仍然保留着遍历过程中的最后一项的值,在后文中仍然可用,for 语句并不能开辟一个独立的作用域,但是如果遍历一次都没有执行,那么临时变量不会被赋值
for range 遍历
对于 C/C++的 for 语法功能,在 Python 中需要通过 range()
函数来辅助实现,或者用 while 实现。
range()
只能使用整数参数,含义如下:
- 三个参数 a,b,c 代表从 a 开始,每次增加的步长为 c(c可以是负数),到 b
停止(不含 b)
- 若步长
c>0
,相当于for(i=a,i<b,i=i+c)
- 若步长
c<0
,相当于for(i=a,i>b,i=i+c)
- 若步长
- 两个参数 a,b 代表从 a 开始,每次增加的步长默认为 c=1,到 b 停止(不含 b)
- 一个参数 b 代表默认从 a=0 开始,每次增加的步长默认为 c=1,到 b 停止(不含 b)
例如
1 | range(5) |
使用 for range()
可以实现 C 风格的 for 循环,例如
1 | for i in range(3,10,2): |
break和continue语句
break 和 continue 就是编程语言中普遍采用的含义:
break
语句可以直接跳出一层 for 或者 while 循环,对于多层循环只能跳出最内层的一层。continue
语句可以直接进入下一轮循环中,跳过当前循环的剩余部分。
else语句
在 while 循环和 for 遍历结构中,我们可以附带 else 分支语句, 在循环正常结束(而非通过break跳出循环)时触发,例如
- while 循环遇到判断条件为 False 时正常退出
- for 遍历正常结束(默认会捕获遍历终止的异常)
例如
1 | digits = [0, 1, 2, 3, 4] |
补充
有几个函数经常在循环语句中使用,这里补充介绍。
zip 函数
zip 函数可以将两个可迭代对象(列表/元组等)的对应项一一对应包装为元组,然后返回一个可迭代的 zip 对象,相当于一个字典的效果。如果两个列表长度不一样,以短的为准,多余的部分被丢弃。
注意这里 for 循环遍历的每一项是含有两个元素的元组,因此可以用两个变量直接解包
1 | a = [1,2,3] |
enumerate 函数
enumerate 函数和 zip 类似,只不过只需要一个列表,会自动给这个列表添加从 0 开始序号,得到一个元组(序号在前,列表元素在后),在 for 遍历中非常方便,因为不仅仅需要迭代的每一项,还需要当前的遍历序号。
1 | animals = ["dog", "cat", "mouse"] |
海象运算符
在if和while语句中,我们需要对一个变量或表达式进行判断,在Python中提供了一个海象运算符可以将逻辑判断和变量赋值结合到一起, 注意这里的变量在if和while语句退出之后仍然可以使用。
在if语句中的用法例如 1
2if (x := len('hello')) > 3:
print(f"The length of 'hello' is {x}")
相当于 1
2
3x = len('hello')
if x>3:
print(f"The length of 'hello' is {x}")
while语句的用法也是类似的,例如 1
2
3file = open("demo.txt", "r")
while (line := file.readline()):
print(line.strip())
相当于 1
2
3
4
5
6file = open("demo.txt", "r")
while True:
line = file.readline()
if not line:
break
print(line.strip())
异常处理
异常处理的流程非常类似于 C++,与C++不同的是在 Python 中并没有严格的函数调用栈之类的,一切都是 Python 解释器提供的动态对象。
捕获异常
捕获异常的语法结构如下:
1 | try: #执行某些不安全的代码 |
例如,下文遍历一个列表直到找到一个有效数据可用于计算倒数
1 | import sys |
抛出异常
除以 0 的操作可以触发一个 ZeroDivisionError
异常,同样地,我们可以自行在语句中使用raise语句抛出异常,例如
1 | try: |
上文中如果输入不满足要求,会抛出 Python 提供的
ValueError
异常,然后立刻捕获异常。
和 C++一样,Python 支持自定义异常,但是要求继承标准异常类
Exception
,略。
断言assert
类似于C语言的assert,在运行时断言表达式为真:如果为真则无事发生,否则抛出异常。
第一种形式 1
assert expression
大致相当于 1
2if __debug__:
if not expression: raise AssertionError
第二种形式会附加信息 1
assert expression1, expression2
大致相当于 1
2if __debug__:
if not expression1: raise AssertionError(expression2)
例如 1
2
3assert x>1
assert ('linux' in sys.platform), "该代码只能在 Linux 下执行"