目录
[1.if-else 双向判断](#1.if-else 双向判断)
[为什么要用 elif 而不是多个独立的 if?](#为什么要用 elif 而不是多个独立的 if?)
[推荐:使用 elif 和 and 减少嵌套](#推荐:使用 elif 和 and 减少嵌套)
[4. match-case 语句(Python 3.10+)----现代化的模式匹配](#4. match-case 语句(Python 3.10+)----现代化的模式匹配)
[为什么需要 match-case?](#为什么需要 match-case?)
[使用 as 绑定整个匹配对象](#使用 as 绑定整个匹配对象)
[注意:不要与 if-else 混淆](#注意:不要与 if-else 混淆)
[6.与循环配合的判断控制:break 和 continue](#6.与循环配合的判断控制:break 和 continue)
[打印 1 到 10 之间的奇数](#打印 1 到 10 之间的奇数)
[输入数字,输入 0 退出](#输入数字,输入 0 退出)
[1. 将最可能发生的分支放在前面](#1. 将最可能发生的分支放在前面)
[2. 使用字典映射取代长链 if-elif](#2. 使用字典映射取代长链 if-elif)
[3. 使用 match-case(Python 3.10+)](#3. 使用 match-case(Python 3.10+))
[4. 避免在循环内做复杂的判断](#4. 避免在循环内做复杂的判断)
[陷阱 1:elif 条件顺序错误](#陷阱 1:elif 条件顺序错误)
[陷阱 2:忘记写 case _ 导致无匹配时什么都不做](#陷阱 2:忘记写 case _ 导致无匹配时什么都不做)
[陷阱 3:在 match-case 中重复使用变量名导致覆盖](#陷阱 3:在 match-case 中重复使用变量名导致覆盖)
[陷阱 4:混淆 for-else 中 else 的触发条件](#陷阱 4:混淆 for-else 中 else 的触发条件)
[最佳实践:优先使用 match-case 而不是冗长的 if-elif](#最佳实践:优先使用 match-case 而不是冗长的 if-elif)
开篇:为什么需要更复杂的判断?
上一篇文章我们只学了 if ------ 它只能决定"做"或"不做"。但现实往往不是黑白二元的:比如根据成绩划分 A、B、C、D、F 五个等级;根据用户输入的命令执行不同操作。这就引出了 if-else(二选一)和 elif(多选一)以及更强大的 match-case(模式匹配)。
1.if-else 双向判断
if-else 双向判断 ------ "如果...否则..."
语法与语义
if 条件:
条件为真时执行的代码块
else:
条件为假时执行的代码块
if后面依然是条件,冒号,缩进块。
else后面跟冒号,但没有条件(因为它是所有剩余情况的兜底)。
else的代码块也需缩进。
生活类比
你在路口过马路:如果 绿灯亮就过马路,否则 就等待。这就是一个标准的 if-else。
score = 55
if score >= 60:
print("及格")
else:
print("不及格")
输出"不及格",因为条件为假。else 部分执行。
注意:else不能单独使用,必须与if配对
else: # SyntaxError
print("no if")

if-else可以嵌套,但是不推荐深度嵌套
嵌套深度超过 2 层时,代码可读性会急剧下降。尽量用 and 或重构函数来减少嵌套。
2.elif多向判断----让程序拥有多个分支
当你有三个或更多互斥的可能性时,if-else 就不够了。你需要 elif(即 else if 的缩写)。
语法结构
if 条件1:
代码块1
elif 条件2:
代码块2
elif 条件3:
代码块3
...
else: # 可选,所有条件都不满足时执行
默认代码块
从上到下依次检查每个条件。
一旦某个条件为
True,就执行对应的代码块,然后跳出整个判断结构 ,不再检查后续的elif或else。如果没有条件为
True,且存在else块,则执行else块;否则什么都不做。
为什么要用 elif 而不是多个独立的 if?
如果用多个独立的 if,每个条件都会独立判断,可能同时执行多个代码块(如果条件有重叠)。而 elif 保证了最多执行一个分支,这是互斥逻辑所需要的。
比如:
错误写法:
score = 85
if score >= 60:
print("及格")
if score >= 80:
print("良好")
# 输出:及格\n良好
正确写法:
if score >= 80:
print("良好")
elif score >= 60:
print("及格")
# 只输出一个
成绩等级示例
我们要实现:90分以上为A,80-89为B,70-79为C,60-69为D,60以下为F。
score = 85
if score >= 90:
grade = 'A'
elif score >= 80:
grade = 'B'
elif score >= 70:
grade = 'C'
elif score >= 60:
grade = 'D'
else:
grade = 'F'
print(f"等级:{grade}")
为什么顺序必须从高到低?
因为条件 score >= 80 其实包含了 score >= 90 的情况,如果把 >=80 写在前面,那么 95 分的同学会被错误地归入 B 等级。Python 执行时会先进入第一个满足的条件,因此必须从高到低写。
季节判断示例(多值匹配)
month = 4
if month in (3, 4, 5):
season = "春季"
elif month in (6, 7, 8):
season = "夏季"
elif month in (9, 10, 11):
season = "秋季"
elif month in (12, 1, 2):
season = "冬季"
else:
season = "无效月份"
print(season)
in 运算符让代码非常直观。
3.嵌套判断的替代方案
嵌套方法:
if is_member:
if spending >= 100:
discount = 0.2
else:
discount = 0.1
else:
discount = 0
优化为 and 逻辑(但这里因为有不同分支,可能不适用)。
另一种优化是提取内部判断为函数。但嵌套并不总是坏的,只要层级不超过 2~3 层且逻辑清晰,也可以接受。
推荐:使用 elif 和 and 减少嵌套
if is_member and spending >= 100:
discount = 0.2
elif is_member:
discount = 0.1
else:
discount = 0
4. match-case 语句(Python 3.10+)----现代化的模式匹配
如果你曾接触过 C/C++ 的 switch-case,你会觉得 match-case 更强大也更优雅。它不仅能匹配具体的值,还能解构数据结构、添加守卫条件。
为什么需要 match-case?
当你有大量基于单个变量值的等值判断时,if-elif 会变得冗长且重复:
if status == 200:
print("OK")
elif status == 404:
print("Not Found")
elif status == 500:
print("Server Error")
# ... 更多
用 match-case 更清晰:
match status:
case 200:
print("OK")
case 404:
print("Not Found")
case 500:
print("Server Error")
case _:
print("Unknown")
基本要点
match后面跟要匹配的表达式(通常是变量)。
case后面跟一个模式(pattern),可以是字面量、变量名、解构模式等。使用
|(或)表示多个模式匹配同一个分支:case 500 | 502 | 503:。
case _是通配符,匹配所有其他情况(类似default)。匹配成功后执行对应的代码块,然后自动跳出 ,不需要**
break**。
解构元组/列表
假设你有一个二维坐标点 (x, y),你想根据坐标值输出不同信息:
point = (0, 0)
match point:
case (0, 0):
print("原点")
case (x, 0):
print(f"X轴上的点,x={x}")
case (0, y):
print(f"Y轴上的点,y={y}")
case (x, y):
print(f"普通点 ({x}, {y})")
这里 case (x, 0) 中的 x 是一个变量,它会自动捕获元组中第一个元素的值。注意:case (0, y) 中的 y 也是如此。这种模式解构非常强大。
守卫(guard)
有时匹配成功还需要额外的条件,比如"两个坐标相等"
point = {0,0}
match point:
case (x, y) if x == y:
print("在对角线上")
case (x, y):
print(f"点 ({x}, {y})")
if x == y 就是守卫条件,只有模式匹配且守卫为真时才进入该分支。
使用 as 绑定整个匹配对象
match items:
case [first, second, *rest] as whole:
print(f"第一个:{first},第二个:{second},剩余:{rest}")
print(f"整个列表:{whole}")
as 可以把匹配到的对象赋值给一个变量,方便后续使用。
性能提示
match-case 并非简单的 if-elif 语法糖,它使用了更高效的跳转表(类似于 C 的 switch),当分支很多时性能优于 if-elif。但更重要的是可读性。
5.循环中的else子句
for 循环和 while 循环后面也可以跟一个 else 子句,它的行为与 if-else 完全不同。很多人第一次见到会困惑。
语法
**for item in iterable:
循环体
if condition:
break
else:循环正常结束(没有被 break 打断)时执行**
while 类似。
判断列表是否包含奇数
numbers = [2, 4, 6, 8]
for n in numbers:
if n % 2 == 1:
print("找到奇数")
break
else:
print("没有奇数") # 因为循环正常结束,没有 break,所以执行这行
如果列表中有奇数,break 会触发,else 就不会执行。这完美地表达了"如果循环没有被提前终止,则执行此代码"。
经典用法:素数检测
num = 17
for i in range(2, num):
if num % i == 0:
print(f"{num} 不是素数,因为能被 {i} 整除")
break
else:
print(f"{num} 是素数")
注意:不要与 if-else 混淆
if-else是二选一,总是执行其中一个。
for-else的else只在循环没有被break终止时执行。如果循环从未执行(比如可迭代对象为空),else也会执行(因为没有 break 发生)。
6.与循环配合的判断控制:break 和 continue
虽然不是判断语句本身,但它们与条件判断紧密配合,控制循环的流程。
-
break:立即结束整个循环,无论循环条件是否满足。 -
continue:跳过本次循环剩余代码,进入下一次迭代。
打印 1 到 10 之间的奇数
for i in range(1, 11):
if i % 2 == 0:
continue # 偶数跳过
print(i)
输入数字,输入 0 退出
while True:
n = int(input("输入数字(0退出):"))
if n == 0:
break
print(f"你输入了 {n}")
这个模式很常见:用 while True 配合 break 来构建"直到满足某个条件才退出"的循环。
7.复杂判断的性能优化技巧
当你的程序需要做很多判断时(比如一个函数里几十个 elif),性能可能会受影响。有以下几种优化方案:
1. 将最可能发生的分支放在前面
if-elif 是顺序判断的,如果能把高频条件放在前面,可以减少平均判断次数。
2. 使用字典映射取代长链 if-elif
当判断条件是等值比较(比如根据状态码执行不同操作)时,可以用字典存储"值->函数"的映射。
def handle_200():
print("OK")
def handle_404():
print("Not Found")
def default_handler():
print("Unknown")
handlers = {
200: handle_200,
404: handle_404,
}
status = 404
handlers.get(status, default_handler)()
handlers.get(status, default_handler)返回handlers[404],即函数对象handle_404。接着
()调用该函数,打印"Not Found"。如果
status不在字典中(例如500),则会返回default_handler并调用,输出"Unknown"。
()是函数调用运算符,它的作用是执行它前面的函数对象。
handlers.get(status, default_handler)返回一个函数对象:
如果
status是 200,返回handle_200如果
status是 404,返回handle_404如果
status是其他值(如 500),返回default_handler然后
()调用这个返回的函数。所以
()本身并不"代表"任何状态码 ,它只是负责执行查找到的函数。真正处理不同状态码的是dict.get()方法,它根据status返回对应的处理函数。
3. 使用 match-case(Python 3.10+)
如上所述,match-case 内部实现可能使用跳转表,对大量分支更高效。
4. 避免在循环内做复杂的判断
可以将判断移到循环外,或者使用向量化操作(如 NumPy)。
8.常见陷阱与最佳实践
陷阱 1:elif 条件顺序错误
如前所述,成绩判断必须从高到低,否则逻辑错误。季节判断则无顺序要求(因为月份互斥),但通常按自然顺序写。
陷阱 2:忘记写 case _ 导致无匹配时什么都不做
有时候你希望无匹配时抛出错误或给出提示,一定要写 case _。
陷阱 3:在 match-case 中重复使用变量名导致覆盖
match point:
case (x, y):
print(x, y)
case (0, 0): # 这里不会匹配,因为 (0,0) 已经被第一个 case 匹配,且 x=0,y=0
print("origin")
case 的顺序也很重要,更具体的模式应放在前面。
陷阱 4:混淆 for-else 中 else 的触发条件
很多初学者以为 else 在循环条件为假时执行,其实它是在循环没有被 break 终止时执行。如果循环被 break 打断,else 不会执行。
最佳实践:优先使用 match-case 而不是冗长的 if-elif
对于单个变量的等值匹配,match-case 可读性更好。但要注意 Python 版本必须 ≥ 3.10。
最佳实践:控制分支深度
如果一个函数里的 if-elif 超过 10 个,或者嵌套深度超过 3 层,应该考虑重构:使用字典映射、策略模式、或者将子逻辑提取为独立函数。
感谢你的观看,期待我们下次再见!