控制流
代码布局不仅影响可读性,更体现了对代码质量的态度。一致的缩进、适当的空行、合理的行长度,这些细节共同构成了优雅的Python代码。
- 使用4个空格进行缩进
- 每行不超过79个字符
- 用空行分隔顶级函数和类定义
条件判断
条件判断是编程中非常基础且重要的概念,它允许我们根据不同的条件执行不同的代码块。
if, elif, else
if condition:
# 当条件为真时执行的代码块
elif condition:
# 当条件为假时执行的代码块
else:
# 当条件都不满足时执行的代码块
a = 62
print("exam score check:")
if a >= 60:
print("student pass")
elif a == 0:
print("student 0: not pass")
else:
print("student not pass")
一个例子
year = 1900
if year % 400 == 0:
print("This is a leap year!")
# 两个条件都满足才执行
elif year % 4 == 0 and year % 100 != 0:
print("This is a leap year!")
else:
print("This is not a leap year.")
# This is not a leap year.
my_list = [1, 2]
# 判断一个列表是否为空。
if len(my_list) > 0:
print("the first element is: ", my_list[0])
else:
print("no element.")
pass 语句
assert 语句
match, case 语句
即便你从未学习过match, case 语句,你也可以轻松的看懂match, case 语句的用法。它是最具有可读性的条件判断语句。
如果需要对一个表达式进行多个条件的判断,可以使用 match, case 语句。
match case 匹配语法更简洁、匹配时自动绑定变量、支持模式组合、支持通配符。尤其对 JSON 数据结构解析非常友好。
当其满足多个条件时,会从上到下依次判断,直到匹配到第一个条件为止。
文字模式与通配符模式
这种写成 _(称为通配符)的特殊模式总是匹配,但它不绑定任何变量。
总是能成功匹配的表达式,我们称其为无可辩驳的。
因此,只有将无可辩驳的表达式单独作为最后一个模式才有意义(为了防止错误,Python 会阻止您之前使用它)。
如果把它放在其他 case 之前,那么后面的 case 块就永远没有机会被执行到,这会使得代码逻辑变得无效或产生问题。
# 在这个例子中,`match` 语句将 `status` 与每个模式进行比较,直到找到一个匹配的模式。
def http_error(status):
match status:
# 代码形式上从 `if status == 400:` 变成了 `case 400:` ,更加简洁。
case 400:
return "Bad request"
case 404:
return "Not found"
case _:
return "Something's wrong with the internet"
for code in [400, 404, 300, 301, 302, 900]:
print(code, http_error(code))
'''
输出:
400 Bad request
404 Not found
300 Redirection
301 Redirection
302 Redirection
Something's wrong with the internet
'''
这种写成 _(称为通配符)的特殊模式总是匹配,但它不绑定任何变量。
match 900:
case _:
print("Something's wrong with the internet")
# 这里会报错,因为 _ 不绑定任何变量
print(_) # NameError: name '_' is not defined
'''
输出:
Something's wrong with the internet
NameError: name '_' is not defined
'''
OR 模式 与 序列模式
def sort(seq): # 定义排序函数,参数为要排序的序列
match seq: # 使用match语句对序列进行模式匹配
# 你可以使用 | (“ or ”)在一个模式中组合几个字面值或模式
# 匹配空列表或单元素列表的情况(注意:同个 | 语句中,绑定变量或不绑定变量要一致)
case [] | [_]:
# 这里 _ 不绑定任何变量,因此可以匹配空列表或单元素列表
# 如果这里写成 [] | [x],则会报错,因为 | 之前不绑定变量,所有后面的语句也不能绑定变量
return seq # 空列表和单元素列表已经有序,直接返回
# 同样下面的2种写法也是不允许的,因为前者绑定了变量为x,后者不能绑定变量为非x(不论是否处于相同位置)
# case [0,x] | [0,y]: # 报错
# case [0,x] | [y,0]: # 报错
# 合法,因为前者后者都绑定同一个变量
# case [0,x] | [x,0]:
# pass
# 使用 if 表达式 结合 case ,匹配两个元素且已经升序排列的情况
case [x, y] if x <= y:
return seq # 已经有序,直接返回原序列
# 匹配两个元素但非升序的情况(因为前者已经匹配了升序的情况)
case [x, y]:
return [y, x] # 交换两个元素的位置并返回
# 使用 if 表达式 结合 case ,匹配三个元素且已经升序排列的情况
case [x, y, z] if x <= y <= z:
return seq # 已经有序,直接返回原序列
# 使用 if 表达式 结合 case ,匹配三个元素且完全降序排列的情况
case [x, y, z] if x >= y >= z:
return [z, y, x] # 完全反转序列并返回
# 匹配包含多个元素的序列,p为第一个元素,rest为剩余元素
case [p, *rest]:
a = sort([x for x in rest if x <= p]) # 递归排序小于等于pivot(p)的元素
b = sort([x for x in rest if p < x]) # 递归排序大于pivot(p)的元素
return a + [p] + b # 合并结果:小于等于p的元素 + p + 大于p的元素
捕获模式
获取匹配结果并绑定到变量即为捕获模式,通配符模式不将匹配结果绑定到变量。
responses = [
["SUCCESS", 200, "OK"],
["ERROR", 404, "Not Found"],
["ERROR", 500, "Server Error"],
["UNKNOWN", 999, "Weird response"]
]
for res in responses:
match res:
# 如果是 SUCCESS,我們捕獲 code 和 message 來顯示
case ["SUCCESS", code, message]:
print(f"✅ Success! Code: {code}, Message: {message}")
# 如果是 ERROR,我們不在乎具體 code 和 message,只想標記為錯誤
case ["ERROR", _, _]:
print("❌ An error occurred.")
# 捕獲所有其他情況
case other:
print(f"❓ Unhandled status: {other}")
'''
输出:
✅ Success! Code: 200, Message: OK
❌ An error occurred.
❌ An error occurred.
❓ Unhandled status: ['UNKNOWN', 999, 'Weird response']
'''
守卫、无可辩驳
三元表达式(条件表达式)
expression1 if condition else expression2
三元表达式是一种简洁的条件赋值方式,相当于简化版的 if-else 语句。
循环
循环是编程中另一个重要的概念,它允许我们重复执行一段代码。
for 循环
# for 循环
total = 0
for i in range(100000):
total += i
print(total) # 4999950000
while 循环
while <condition>:
<statesments>
Python 会循环执行statesments,直到condition不满足为止。
i = 0
total = 0
while i <= 100:
total += i
i += 1
print(total) # 5050
举个例子,通过 while 遍历集合:
# 空容器会被当成False,因此可以用while循环读取容器的所有元素
plays = set(['Hamlet', 'Mac', 'King'])
while plays:
play = plays.pop()
print('Perform', play)
continue 语句
遇到 continue 的时候,程序会返回到循环的最开始重新执行。
values = [7, 6, 4, 7, 19, 2, 1]
for i in values:
if i % 2 != 0:
# 忽略奇数
continue
print(i)
# 6
# 4
# 2
break 语句
遇到 break 的时候,程序会跳出循环,不管循环条件是不是满足
command_list = ['start',
'1',
'2',
'3',
'4',
'stop',
'restart',
'5',
'6']
while command_list:
command = command_list.pop(0)
if command == 'stop':
break
print(command)
# start
# 1
# 2
# 3
# 4
异常处理
try & except &finally
捕捉不同的错误类型,尝试在下面输入框输入:-1,1,2,q
import math
while True:
try:
text = input('>')
if text[0] == 'q':
break
x = float(text)
y = 1 / math.log10(x)
print("1/log10({0}) = {1}".format(x, y))
except ValueError:
print("value must bigger than 0")
except ZeroDivisionError:
print("the value must not be 1")
try/catch 块还有一个可选的关键词 finally。
不管 try 块有没有异常, finally 块的内容总是会被执行, 而且会在抛出异常前执行,因此可以用来作为安全保证,
比如文件操作时,常在 finally 关闭文件。
try:
print(1 / 0)
except ZeroDivisionError:
print('divide by 0.')
finally:
print('finally was called.')
raise 语句
frame对except的影响
以下代码在 Python3.12.9 中依然存在。
e = 1
try:
0/0 # 此处会抛出错误,因为0不能被0除
except Exception as e:
# 此处会对覆盖e,并删除e
print(f'error info :{e}!')
print(e)
'''
输出:
error info :division by zero!
Traceback (most recent call last):
File "c:\Users\jiang\Desktop\todo\1.py", line 7, in <module>
print(e)
^
NameError: name 'e' is not defined
'''
下面的代码更有可能在生产环境中出现,原理相同,报错信息同样为:NameError: name 'e' is not defined
try:
e = eval(input("please input 0/0:"))
except Exception as e:
pass
finally:
print(e)
内置函数
以下函数大多为操作序列与控制流一起使用。