Day11 · 流程控制(一)分支

Day11 · 流程控制(一)分支

阶段:阶段一 · 核心基础 | 前置:Day10 | 技术基准:Python 3.15.0

学习目标

  • 掌握顺序、分支、循环三大程序结构的概念,重点吃透分支结构
  • 熟练写出 if / if...else / if...elif...else 三种分支
  • 会用三元表达式、嵌套分支解决实际问题
  • 掌握 Python 3.10+ 引入、3.15 完全成熟的 match...case 结构化模式匹配
  • 避开分支里的常见坑:缩进、== vs is、空值判断、冒号遗漏

到目前为止,我们写的程序都是"从上到下一行一行顺序执行"。但真实世界里充满了选择:成绩 ≥60 就及格,否则补考;登录成功进主页,失败就提示密码错误。这种"根据条件走不同岔路"的能力,就是分支结构。

程序一共有三种基本结构:顺序结构(一行接一行)、分支结构(按条件选路)、循环结构(重复执行,Day12 讲)。任何复杂程序都是这三种结构拼出来的。

一、if 单分支

1.1、语法

if 布尔表达式:
    条件成立时要做的事

注意两个铁律:

  1. 条件后面必须有冒号 :(漏写是初学者第一大语法错误);
  2. 冒号下一行必须缩进(约定 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 而硬套,工具服务于代码。

练习题

  1. 写一个程序:输入一个整数,判断它是正数、负数还是零。

  2. 把成绩等级案例改写成 match...case 版本(提示:先把分数换算成等级区间再匹配,或自己设计输入)。

  3. 用三元表达式写:输入一个数,输出它的绝对值(不许用 abs())。

  4. 写一个" BMI 指数计算器":输入身高(米)和体重(公斤),算出 BMI = 体重 / 身高²,按 <18.5 偏瘦、18.5~24 正常、>24 偏胖 输出结论。

  5. 思考题:if a == b 和 if a is b 在什么情况下结果会不一样?为什么判断 None 推荐用 is?

  6. 找一找下面代码的 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 混用、空值判断、把 == 写成 =。

扩展阅读

posted @ 2026-11-03 16:51  小嘉游戏  阅读(4)  评论(0)    收藏  举报