1
0
wiki/dev/Python/控制语句.md

307 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: 控制语句
title: 控制语句
sidebar_position: 2
data: 2022年2月9日
---
## 判断
### if
在Python中要构造分支结构可以使用`if`、`elif`和`else`关键字。
```python
"""
用户身份验证
Version: 0.1
Author: 骆昊
"""
username = input('请输入用户名: ')
password = input('请输入口令: ')
# 用户名是admin且密码是123456则身份验证成功否则身份验证失败
if username == 'admin' and password == '123456':
print('身份验证成功!')
else:
print('身份验证失败!')
```
当然如果要构造出更多的分支,可以使用`if...elif...else...`结构或者嵌套的`if...else...`结构。
### match
match 语句接受一个表达式并将它的值与以一个或多个 case 语句块形式给出的一系列模式进行比较。 这在表面上很类似 C, Java 或 JavaScript (以及许多其他语言) 中的 switch 语句,但它还能够从值中提取子部分 (序列元素或对象属性) 并赋值给变量。
```python
def 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"
```
最后一个代码块: "变量名" `_` 被作为 *通配符* 并必定会匹配成功。 如果没有任何 case 语句匹配成功,则任何分支都不会被执行。
你可以使用 `|` (“ or ”)在一个模式中组合几个字面值:
```python
case 401 | 403 | 404:
return "Not allowed"
```
## 循环
### for
Python 的 for 语句与 C 或 Pascal 中的不同。Python 的 for 语句不迭代算术递增数值(如 Pascal或是给予用户定义迭代步骤和暂停条件的能力如 C而是迭代列表或字符串等任意序列元素的迭代顺序与在序列中出现的顺序一致。
```python
"""
用for循环实现1~100求和
Version: 0.1
Author: 骆昊
"""
sum = 0
for x in range(101):
sum += x
print(sum)
```
`range(101)`可以用来构造一个从1到100的范围当我们把这样一个范围放到`for-in`循环中,就可以通过前面的循环变量`x`依次取出从1到100的整数。当然`range`的用法非常灵活,下面给出了一个例子:
- `range(101)`可以用来产生0到100范围的整数需要注意的是取不到101。
- `range(1, 101)`可以用来产生1到100范围的整数相当于前面是闭区间后面是开区间。
- `range(1, 101, 2)`可以用来产生1到100的奇数其中2是步长即每次数值递增的值。
- `range(100, 0, -2)`可以用来产生100到1的偶数其中-2是步长即每次数字递减的值。
### while
如果要构造不知道具体循环次数的循环结构,那么使用`while`循环通过一个能够产生或转换出`bool`值的表达式来控制循环,表达式的值为`True`则继续循环;表达式的值为`False`则结束循环。
```python
"""
猜数字游戏
Version: 0.1
Author: 骆昊
"""
import random
answer = random.randint(1, 100)
counter = 0
while True:
counter += 1
number = int(input('请输入: '))
if number < answer:
print('大一点')
elif number > answer:
print('小一点')
else:
print('恭喜你猜对了!')
break
print('你总共猜了%d次' % counter)
if counter > 7:
print('你的智商余额明显不足')
```
### break
break 语句和 C 中的类似,用于跳出最近的 for 或 while 循环。
### continue
continue 语句也借鉴自 C 语言,表示继续执行循环的下一次迭代。
### else
循环语句支持 else 子句for 循环中,可迭代对象中的元素全部循环完毕时,或 while 循环的条件为假时执行该子句break 语句终止循环时,不执行该子句。
```python
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print(n, 'equals', x, '*', n//x)
break
else:
# loop fell through without finding a factor
print(n, 'is a prime number')
"""
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3
"""
```
## 异常
### try、except、finally
1. `except`语句不是必须的,`finally`语句也不是必须的,但是二者必须要有一个,否则就没有`try`的意义了。
2. `except`语句可以有多个Python会按`except`语句的顺序依次匹配你指定的异常,如果异常已经处理就不会再进入后面的`except`语句。
3. `except`语句可以以元组形式同时指定多个异常,参见实例代码。
4. `except`语句后面如果不指定异常类型则默认捕获所有异常你可以通过logging或者sys模块获取当前异常。
5. 如果要捕获异常后要重复抛出,请使用`raise`,后面不要带任何参数或信息。
6. 不建议捕获并抛出同一个异常,请考虑重构你的代码。
7. 不建议在不清楚逻辑的情况下捕获所有异常,有可能你隐藏了很严重的问题。
8. 尽量使用内置的异常处理语句来替换`try/except`语句,比如`with`语句,`getattr()`方法。
```python
def div(a, b):
try:
print(a / b)
except ZeroDivisionError:
print("Error: b should not be 0 !!")
except Exception as e:
print("Unexpected Error: {}".format(e))
else:
print('Run into else only when everything goes well')
finally:
print('Always run into finally block.')
# tests
div(2, 0)
div(2, 'bad type')
div(1, 2)
# Mutiple exception in one line
try:
print(a / b)
except (ZeroDivisionError, TypeError) as e:
print(e)
# Except block is optional when there is finally
try:
open(database)
finally:
close(database)
# catch all errors and log it
try:
do_work()
except:
# get detail from logging module
logging.exception('Exception caught!')
# get detail from sys.exc_info() method
error_type, error_value, trace_back = sys.exc_info()
print(error_value)
raise
```
### raise
`raise`语句支持强制触发指定的异常。例如:
```python
raise NameError('HiThere')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: HiThere
```
## 其他
### pass
pass 语句不执行任何操作。语法上需要一个语句,但程序不实际执行任何动作时,可以使用该语句。例如:
```python
while True:
pass # Busy-wait for keyboard interrupt (Ctrl+C)
# 最小的类
class MyEmptyClass:
pass
```
### del
目标列表的删除将从左至右递归地删除每一个目标
```python
del a
del b[]
```
### return
return 会离开当前函数调用,并以表达式列表 (或 None) 作为返回值。
### yield
生成迭代器
```python
def foo(num):
print("starting...")
while num<10:
num=num+1
yield num
for n in foo(0):
print(n)
# 输出
starting...
1
2
3
4
5
6
7
8
9
10
```
### import
基本的 import 语句(不带 from 子句)会分两步执行:
1. 查找一个模块,如果有必要还会加载并初始化模块。
2. 在局部命名空间中为 import 语句发生位置所处的作用域定义一个或多个名称。
```python
import foo # foo imported and bound locally
import foo.bar.baz # foo.bar.baz imported, foo bound locally
import foo.bar.baz as fbb # foo.bar.baz imported and bound as fbb
from foo.bar import baz # foo.bar.baz imported and bound as baz
from foo import attr # foo imported and foo.attr bound as attr
```
from 形式使用的过程略微繁复一些:
1. 查找 from 子句中指定的模块,如有必要还会加载并初始化模块;
2. 对于 import 子句中指定的每个标识符:
1. 检查被导入模块是否有该名称的属性
2. 如果没有,尝试导入具有该名称的子模块,然后再次检查被导入模块是否有该属性
3. 如果未找到该属性,则引发 ImportError。
4. 否则的话,将对该值的引用存入局部命名空间,如果有 as 子句则使用其指定的名称,否则使用该属性的名称
### global
global 语句是作用于整个当前代码块的声明。 它意味着所列出的标识符将被解读为全局变量。
### nonlocal
nonlocal 语句会使得所列出的名称指向之前在最近的包含作用域中绑定的除全局变量以外的变量。