Day11 · 流程控制(一)分支
Day11 · 流程控制(一)分支
阶段:阶段一 · 核心基础 | 前置:Day10 | 技术基准:Python 3.15.0
学习目标
- 掌握顺序、分支、循环三大程序结构的概念,重点吃透分支结构
- 熟练写出
if/if...else/if...elif...else三种分支 - 会用三元表达式、嵌套分支解决实际问题
- 掌握 Python 3.10+ 引入、3.15 完全成熟的
match...case结构化模式匹配 - 避开分支里的常见坑:缩进、
==vsis、空值判断、冒号遗漏
到目前为止,我们写的程序都是"从上到下一行一行顺序执行"。但真实世界里充满了选择:成绩 ≥60 就及格,否则补考;登录成功进主页,失败就提示密码错误。这种"根据条件走不同岔路"的能力,就是分支结构。
程序一共有三种基本结构:顺序结构(一行接一行)、分支结构(按条件选路)、循环结构(重复执行,Day12 讲)。任何复杂程序都是这三种结构拼出来的。
一、if 单分支
1.1、语法
if 布尔表达式:
条件成立时要做的事
注意两个铁律:
- 条件后面必须有冒号
:(漏写是初学者第一大语法错误); - 冒号下一行必须缩进(约定 4 个空格),缩进的那段就是"条件成立时执行的代码块"。
# Author: XiaoJia
# 输入两个数 a、b,只有当 a > b 时才提示
a = float(input("a = "))
b = float(input("b = "))
if a > b:
print(f"{a} 大于 {b}")
print("这行无论如何都会执行")
当 a <= b 时,if 下面缩进的那段被跳过,直接执行最后一行。
二、if...else 双分支
只有一个出口往往不够——条件不成立时也想做点什么,就用 else:
if 布尔表达式:
条件成立时执行
else:
条件不成立时执行
# Author: XiaoJia
# 判断奇偶
num = int(input("请输入一个整数:"))
if num % 2 == 0:
print(f"{num} 是偶数")
else:
print(f"{num} 是奇数")
三、if...elif...else 多分支
现实里岔路常常不止两条(成绩要分优秀/良好/及格/不及格),这时用 elif(else if 的缩写)串联多个条件:
if 条件1:
...
elif 条件2:
...
elif 条件3:
...
else:
以上都不满足时执行
# Author: XiaoJia
# 成绩等级判定
score = float(input("请输入你的成绩:"))
if score >= 90:
print("优秀")
elif score >= 80:
print("良好")
elif score >= 60:
print("及格")
else:
print("不及格,需要补考")
3.1、多条件的两个要点
- 从上往下依次判断,命中一个就跳出:比如 95 分命中第一个
>=90后,后面的分支根本不会再判断。所以条件要"从严到松"排序——上面写>=60再写>=90就会让所有 ≥60 的人都提前掉进"及格",逻辑全错。 else可省略,但建议保留:省略else在语法上没问题,但小嘉建议永远写一个兜底的else(哪怕里面只打一句日志),这样未来数据出现意外时你能立刻发现。
3.2、多个条件的组合:and / or / not
Day09 讲过逻辑运算符,在分支里大量使用:
# Author: XiaoJia
age = int(input("年龄:"))
has_ticket = input("是否有票(y/n):") == "y"
# 两个条件同时满足
if age >= 18 and has_ticket:
print("可以入场")
else:
print("不能入场")
# 任一条件满足
if age < 12 or age > 65:
print("享受优惠票")
# 取反
if not has_ticket:
print("请先购票")
四、三元表达式(条件表达式)
很多时候我们只是想"根据条件二选一地赋个值",写完整的 if/else 太啰嗦。Python 提供了三元表达式:
值 = 表达式A if 条件 else 表达式B
含义:条件成立取表达式 A,否则取表达式 B。
# Author: XiaoJia
age = int(input("年龄:"))
# 啰嗦版
if age >= 18:
status = "成年"
else:
status = "未成年"
# 简洁版(等价)
status = "成年" if age >= 18 else "未成年"
print(status)
# 直接在 print 里用
print("偶数" if age % 2 == 0 else "奇数")
注意它和 C/Java 的 条件 ? A : B 顺序不一样——Python 是把"结果 A"写在最前面。
五、嵌套分支
分支内部还可以再套分支,形成多层判断:
# Author: XiaoJia
# 登录 + 权限判断
username = input("用户名:")
password = input("密码:")
if username == "admin":
if password == "123456":
print("登录成功,欢迎管理员")
else:
print("密码错误")
else:
print("用户不存在")
嵌套层数别太深(一般不超过 3 层),否则可读性急剧下降。能用 and 合并的条件就合并:
# Author: XiaoJia
# 等价写法,用 and 把外层内层合并,更扁平
if username == "admin" and password == "123456":
print("登录成功,欢迎管理员")
elif username != "admin":
print("用户不存在")
else:
print("密码错误")
六、match...case 结构化模式匹配(3.10+,3.15 成熟)
Python 3.10 引入了 match...case(PEP 634),类似其他语言的 switch,但远不止 switch——它能对值、结构、类型做模式匹配。3.15 里它已经完全成熟,推荐替代"一长串 if...elif =="的写法。
6.1、基本形态:按值匹配
# Author: XiaoJia
command = input("请输入命令(start/stop/restart):")
match command:
case "start":
print("启动服务")
case "stop":
print("停止服务")
case "restart":
print("重启服务")
case _:
print("未知命令") # _ 是通配符,相当于 else 兜底
要点:
match 表达式:后接若干case 值:;case _通配所有情况,相当于else,放最后;- Python 的 match 不会像 C 的 switch 那样"穿透",命中一个 case 就结束,不需要
break。
6.2、带"|"的多值匹配
# Author: XiaoJia
season = input("季节:")
match season:
case "春天" | "春":
print("春暖花开")
case "夏天" | "夏":
print("烈日炎炎")
case "秋天" | "秋":
print("秋高气爽")
case "冬天" | "冬":
print("白雪皑皑")
case _:
print("输入有误")
一个 case 里用 | 表示"满足任意一个值都行"。
6.3、匹配结构与绑定(进阶感知)
match 真正强大的地方是能拆包匹配序列,这里先建立印象(Day15、Day16 后会更熟练):
# Author: XiaoJia
# 根据坐标点的结构做不同处理
def handle(point):
match point:
case (0, 0):
return "原点"
case (0, y):
return f"落在 Y 轴上,y={y}" # y 被绑定为实际值
case (x, 0):
return f"落在 X 轴上,x={x}"
case (x, y):
return f"普通点 ({x}, {y})"
print(handle((0, 0))) # 原点
print(handle((0, 5))) # 落在 Y 轴上,y=5
print(handle((3, 4))) # 普通点 (3, 4)
七、分支里的常见坑
7.1、缩进错误
Python 靠缩进区分代码块,缩进错乱是新手第一大报错来源:
# Author: XiaoJia
# 错误示例:if 下面必须有缩进块,否则 IndentationError
# if True:
# print("hi") # 这行没有缩进,会报错
# Tab 和空格不要混用!统一用 4 个空格(编辑器一般会自动把 Tab 转空格)
7.2、== 与 is 别混用
== 比较的是值是否相等;is 比较的是是不是同一个对象。分支里判断相等几乎永远该用 ==:
# Author: XiaoJia
a = [1, 2]
b = [1, 2]
print(a == b) # True 值相等
print(a is b) # False 是两个不同的列表对象
# 判断"是否为 None"时才推荐用 is
x = None
if x is None:
print("x 是空的") # 正确:判 None 用 is
小嘉提醒:因为"小整数缓存、字符串驻留"(Day06 讲过),有时候
a is b碰巧为 True,让你误以为is能用——这是假象。比较值就用==。
7.3、空值判断:善用"真假"
Python 里这些值在 if 中都被视为假(False):0、0.0、""(空字符串)、[](空列表)、{}(空字典)、None。其余大多为真。所以判空可以写得很简洁:
# Author: XiaoJia
name = ""
# 啰嗦
if name != "":
print("你好", name)
# 推荐:直接写 if name(空字符串为假)
if name:
print("你好", name)
else:
print("名字不能为空")
# 判 None 要单独用 is None
data = None
if data is None:
print("没有数据")
7.4、把赋值写成 == 与海象运算符
if a = 10: 在 Python 里是语法错误(不能直接在条件里赋值)。Python 3.8 起引入海象运算符 :=,可以在条件里边赋值边判断,3.15 完全支持:
# Author: XiaoJia
# 海象运算符 := 可以在条件里边赋值边判断
# 例如:当读入的密码长度够 6 位就进入
if (pwd := input("密码:")) and len(pwd) >= 6:
print(f"密码长度 {len(pwd)},合格")
else:
print("密码太短")
八、真值规则与分支设计原则
8.1、条件里到底什么算"真"
if 后面跟的不一定是显式的 True/False,任何表达式都能当条件。Python 会用内置函数 bool() 把它转换成真假。记住这张"假值表",其余一律为真:
- 常量:
False、None; - 数值零:
0、0.0、0j(复数零); - 空容器:
""(空字符串)、[](空列表)、{}(空字典)、set()(空集合)、()(空元组); - 自定义对象默认都为真,除非自己定义了
__bool__或__len__(Day20 讲)。
这意味着 if name: 等价于 if bool(name) is True: 但更地道。反过来,不要写 if name == True:——除非你真的只想要布尔真,因为 "yes" == True 是 False,但 "yes" 在条件里是真的。
8.2、链式比较与短路对分支的影响
Day09 讲过比较运算符可以链式写 if 60 <= score < 90:,这比 if score >= 60 and score < 90: 更清晰,分支里推荐用。另外,and/or 是短路的:if a and b: 中若 a 为假,b 根本不会被求值。利用这一点可以安全取值:if user and user.is_active:——user 是 None 时直接短路,不会去访问 None.is_active 而崩溃。
8.3、什么时候用 match,什么时候用 if 链
经验法则:分支值是"离散的几个具体取值"(命令名、状态码、季节)时用 match,可读性明显更好;分支条件是连续区间、复杂范围、多个条件组合时用 if...elif,因为 match 的 case 擅长匹配值和结构,不擅长写区间不等式。别为了用 match 而硬套,工具服务于代码。
练习题
-
写一个程序:输入一个整数,判断它是正数、负数还是零。
-
把成绩等级案例改写成
match...case版本(提示:先把分数换算成等级区间再匹配,或自己设计输入)。 -
用三元表达式写:输入一个数,输出它的绝对值(不许用
abs())。 -
写一个" BMI 指数计算器":输入身高(米)和体重(公斤),算出 BMI = 体重 / 身高²,按 <18.5 偏瘦、18.5~24 正常、>24 偏胖 输出结论。
-
思考题:
if a == b和if a is b在什么情况下结果会不一样?为什么判断None推荐用is? -
找一找下面代码的 bug:输入成绩后,无论输多少都打印"及格",为什么?
score = float(input()) if score >= 60: print("及格") if score >= 80: print("良好")
小结
- 程序三大结构:顺序、分支、循环;分支用
if家族实现。 if/if...else/if...elif...else;条件后必须冒号,下一行必须缩进。- 多条件用
and/or/not;多分支条件要"从严到松"排序,建议保留else兜底。 - 三元表达式
A if 条件 else B适合二选一赋值。 match...case(3.10+,3.15 成熟)用于多路分支,case _兜底,命中即跳出无需break。- 常见坑:缩进、漏冒号、
==与is混用、空值判断、把==写成=。
扩展阅读
- 官方文档 · 控制流 if:https://docs.python.org/3/tutorial/controlflow.html
- PEP 634 结构化模式匹配:https://peps.python.org/pep-0634/

浙公网安备 33010602011771号