Python 语法篇 · 第4章

流程控制:分支与循环

让程序学会"做判断"和"重复做事"。本章讲透 if 分支、match-case、while/for 循环及经典循环案例。

🎯 学习目标

  • 理解顺序、分支、循环三种基本程序结构
  • 熟练使用 if / elif / else,掌握 Python 缩进规则
  • 了解 Python 3.10 的 match-case 结构化模式匹配
  • 熟练使用 while 与 for + range 遍历
  • 区分 break、continue、pass 与循环 else
  • 能独立写出九九乘法表、猜数字、累加求和等经典案例

1三种程序结构与缩进规则

任何复杂程序都由三种基本结构搭建而成:

  • 顺序结构:代码从上到下逐行执行(默认形态)。
  • 分支结构:根据条件选择执行路径(if)。
  • 循环结构:满足条件时重复执行一段代码(while/for)。

缩进是 Python 语法的一部分!其他语言用花括号 { } 表示代码块,Python 用冒号 + 缩进。同一层级代码必须缩进相同(PEP 8 规定 4 个空格),缩进错乱会直接报 IndentationError。在 VS Code 中按 Tab 会自动插入 4 个空格。

2if 条件分支

2.1 基本形式

age = 20

if age >= 18:               # 注意末尾冒号
    print("已成年")          # 条件成立时执行(缩进4空格)
    print("可以考驾照")
else:
    print("未成年")

print("分支结束")            # 回到外层缩进 = 不属于任何分支

2.2 多分支:if / elif / else

score = 82

if score >= 90:
    grade = "优秀"
elif score >= 80:          # else if 必须连写成 elif
    grade = "良好"
elif score >= 60:
    grade = "及格"
else:
    grade = "不及格"

print(grade)               # 良好

# 条件按顺序判断,命中一个后整条链立即结束(后续不再判断)
# 因此分支顺序会影响结果,要把更严格的条件放前面

2.3 条件的写法

name = ""

# Pythonic 写法:直接利用真值测试,不必写 != ""
if name:
    print("有名字")
else:
    print("名字为空")

# 多条件组合
is_weekend = True
is_holiday = False
if is_weekend or is_holiday:
    print("休息")

# 链式比较
temperature = 26
if 18 <= temperature <= 26:
    print("温度舒适")

# 逻辑取反:推荐 not in / is not 这种"自然语序"
blocked = ["spam", "ad"]
content = "hello"
if content not in blocked:
    print("内容正常")

2.4 嵌套 if(不要超过三层)

has_ticket = True
has_id = True

if has_ticket:
    if has_id:
        print("检票进站")
    else:
        print("请出示身份证")
else:
    print("请先购票")

嵌套过多会形成"箭头型代码"难以阅读。可优先用卫语句(提前 return/结束)或用 and 合并条件来减少层级。

2.5 案例:BMI 健康指数

weight = float(input("体重(kg):"))
height = float(input("身高(m):"))
bmi = weight / height ** 2

if bmi < 18.5:
    advice = "偏瘦"
elif bmi < 24:
    advice = "正常"
elif bmi < 28:
    advice = "超重"
else:
    advice = "肥胖"

print(f"BMI={bmi:.1f},{advice}")

3match-case 模式匹配(Python 3.10+)

当分支特别多、需要对值或数据结构匹配时,match-case 比长串 elif 更清晰(类似其他语言的 switch,但强大得多):

status = 404

match status:
    case 200:
        print("OK")
    case 404:
        print("Not Found")
    case 500 | 502 | 503:          # | 表示多个值之一
        print("服务器错误")
    case _:                         # _ 是通配符,相当于 default
        print("其他状态码")

它还能直接解构列表、字典、对象(结构化匹配):

point = (3, 4)

match point:
    case (0, 0):
        print("原点")
    case (0, y):
        print(f"在 y 轴上,y={y}")
    case (x, 0):
        print(f"在 x 轴上,x={x}")
    case (x, y):
        print(f"普通点 ({x}, {y})")   # 命中

# 带守卫条件的匹配
command = {"action": "login", "user": "admin"}
match command:
    case {"action": "login", "user": user}:
        print(f"用户 {user} 登录")
    case _:
        print("未知指令")

4while 循环

当条件为真时反复执行代码块,先判断、后执行:

# 1 到 5 累加
total = 0
i = 1
while i <= 5:
    total += i
    i += 1               # 千万别忘更新循环变量!
print(total)             # 15

忘记 i += 1 会导致条件永远为真,形成死循环。在终端按 Ctrl + C 可强制终止程序。

案例:猜数字游戏

import random

answer = random.randint(1, 100)
times = 0

while True:                              # 无条件循环,靠 break 退出
    guess = int(input("猜一个 1~100 的数:"))
    times += 1
    if guess < answer:
        print("小了")
    elif guess > answer:
        print("大了")
    else:
        print(f"恭喜,猜了 {times} 次!")
        break                            # 猜对才退出

5for 循环与 range

for 用于遍历可迭代对象(字符串、列表、range 等),"依次取出每个元素":

for ch in "Python":
    print(ch, end=" ")          # P y t h o n

for item in [10, 20, 30]:
    print(item)

# range(起, 止, 步长):生成整数序列,含头不含尾
for i in range(5):              # 0 1 2 3 4(从0开始,不到5)
    print(i, end=" ")
print()
for i in range(1, 10, 2):       # 1 3 5 7 9
    print(i, end=" ")
print()
for i in range(5, 0, -1):       # 5 4 3 2 1(倒序)
    print(i, end=" ")
写法产生的序列典型用途
range(n)0,1,…,n-1重复 n 次
range(a, b)a,…,b-1按下标遍历
range(a, b, s)从 a 起步长 s,不到 b奇数、倒序等

同时需要下标和元素:enumerate

fruits = ["苹果", "香蕉", "橙子"]

# 不推荐:手动维护下标
i = 0
for f in fruits:
    print(i, f)
    i += 1

# 推荐:enumerate 自动给出 (序号, 元素),序号可指定起始值
for idx, f in enumerate(fruits, start=1):
    print(f"第{idx}个水果是{f}")

6break、continue、pass 与循环 else

关键字作用
break立即跳出整个当前循环
continue跳过本次循环剩余语句,直接进入下一次
pass空语句,占位用,什么都不做(保持语法完整)
# continue:只输出偶数
for i in range(1, 8):
    if i % 2 != 0:
        continue          # 奇数:跳过后面的 print
    print(i, end=" ")     # 2 4 6
print()

# break:找到第一个 7 的倍数即停止
for i in range(1, 100):
    if i % 7 == 0:
        print("找到:", i)
        break             # 7
# pass:还没想好函数/分支写什么,先占位防止语法错误
def todo():
    pass                  # TODO: 以后实现

if False:
    pass                  # 空分支
else:
    print("执行这里")

循环的 else 子句(Python 特色)

循环正常结束(没有被 break 打断)时执行 else 中的代码,常用于"查找"逻辑:

# 判断 n 是否为质数
n = 17
for i in range(2, int(n ** 0.5) + 1):
    if n % i == 0:
        print(n, "不是质数,因子", i)
        break
else:
    print(n, "是质数")     # 循环中从未 break → 完整跑完 → 进入 else

7嵌套循环:九九乘法表

# 外层控制行(被乘数),内层控制列(乘数)
for i in range(1, 10):
    for j in range(1, i + 1):
        print(f"{j}×{i}={i*j:<2d}", end="  ")
    print()                # 每行结束换行
1×1=1
1×2=2   2×2=4
1×3=3   2×3=6   3×3=9
...(共 9 行)

外层循环走 1 次,内层循环走 1 整轮。打印图形时通用套路:"外层管行数,内层管每行内容,print() 换行"。

案例:打印直角三角形与求阶乘

# 星号三角形
for i in range(1, 6):
    print("*" * i)

# n 的阶乘 n! = 1×2×...×n
n, result = 5, 1
for i in range(1, n + 1):
    result *= i
print(result)             # 120

8推导式初步(第12章深入)

Python 提供了"边循环边构造列表"的简洁语法——列表推导式:

# 求 1~9 的平方
squares = [i ** 2 for i in range(1, 10)]
print(squares)            # [1, 4, 9, 16, 25, 36, 49, 64, 81]

# 带条件筛选:只要偶数的平方
even_sq = [i ** 2 for i in range(1, 10) if i % 2 == 0]
print(even_sq)            # [4, 16, 36, 64]

# 等价的传统写法(4行 vs 推导式1行)
even_sq2 = []
for i in range(1, 10):
    if i % 2 == 0:
        even_sq2.append(i ** 2)

9综合案例

案例1:登录验证(最多 3 次机会)

PASSWORD = "123456"

for attempt in range(3, 0, -1):
    pwd = input(f"请输入密码(剩余{attempt}次):")
    if pwd == PASSWORD:
        print("登录成功")
        break
    print("密码错误")
else:
    print("次数用完,账号锁定")

案例2:统计一组成绩的平均分与及格率

scores = [88, 45, 76, 92, 59, 100, 67]
total = passed = 0

for s in scores:
    total += s
    if s >= 60:
        passed += 1

print(f"平均分:{total / len(scores):.1f}")
print(f"及格率:{passed / len(scores) * 100:.0f}%")
平均分:75.3
及格率:71%

10本章小结与练习

📌 关键结论

  • Python 靠冒号 + 4 空格缩进划分代码块。
  • 多分支用 elif(不是 else if);条件直接写真值测试最地道。
  • 循环次数明确用 for + range;条件驱动用 while。
  • break 退出整层循环;continue 跳过本次;循环 else 在"未被 break"时执行。
  • 遍历同时要序号用 enumerate,不要手动维护 i。
练习1:用 for 循环输出 1~100 中所有 7 的倍数(或含数字 7 的数)。
for n in range(1, 101): if n % 7 == 0 or '7' in str(n): print(n, end=' ') 整除取倍数;str(n) 后用 in 判断是否含字符 7。
练习2:用循环判断 151、12321、123 是否为回文数(正读反读相同)。
简洁写法:n = 12321; s = str(n); print(s == s[::-1])([::-1] 是字符串逆序切片,第5章详讲)。纯算术可用 while 不断取 n%10 拼出逆序数再比较。
练习3:while 循环中忘了写更新语句会怎样?如何排查?
条件永远成立造成死循环,程序卡住不结束。排查:①检查循环变量是否在循环体内被修改;②在循环内 print 关键变量观察;③终端 Ctrl+C 终止。也可在代码审查时确认每条 while 都有明确的退出条件(或 break)。