第 4 章 流程控制
4.1 条件语句:if / elif / else
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}") # B
三元表达式(条件表达式)
age = 20
status = "成年" if age >= 18 else "未成年"
print(status) # 成年
# 嵌套三元(可读性差,不推荐超过一层)
x = 15
label = "大" if x > 10 else ("中" if x > 5 else "小")
条件表达式的惯用法
# 取绝对值(当然实际用 abs())
x = -5
result = x if x >= 0 else -x
# 限制范围
value = 150
clamped = max(0, min(100, value)) # 100
# 空值处理
name = None
display_name = name if name is not None else "匿名用户"
# 更简洁(但注意空字符串也会触发)
display_name = name or "匿名用户"
4.2 match-case 结构化模式匹配(Python 3.10+)
match-case 远不只是 switch-case,它支持结构化模式匹配:
基本值匹配
command = "quit"
match command:
case "start":
print("启动")
case "stop":
print("停止")
case "quit" | "exit": # 或模式
print("退出")
case _: # 通配符,匹配任何值
print("未知命令")
序列模式
point = (3, 4)
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})")
映射模式(字典)
event = {"type": "click", "x": 100, "y": 200}
match event:
case {"type": "click", "x": x, "y": y}:
print(f"点击位置: ({x}, {y})")
case {"type": "keypress", "key": key}:
print(f"按下键: {key}")
case {"type": t}:
print(f"未处理的事件类型: {t}")
类模式
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
# 需要 __match_args__ 来支持位置模式
__match_args__ = ("x", "y")
p = Point(1, 0)
match p:
case Point(0, 0):
print("原点")
case Point(x, 0):
print(f"x 轴上: {x}")
case Point(x, y) if x == y: # 守卫条件
print(f"在对角线上: ({x}, {y})")
case Point(x, y):
print(f"普通点: ({x}, {y})")
嵌套与解包
data = {"users": [{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]}
match data:
case {"users": [{"name": first_name}, *rest]}:
print(f"第一个用户: {first_name}, 还有 {len(rest)} 个用户")
4.3 for 循环与可迭代对象
Python 的 for 循环遍历的是可迭代对象,不是索引:
# 遍历列表
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
# 遍历字符串
for char in "Python":
print(char, end=" ") # P y t h o n
# 遍历字典
person = {"name": "Alice", "age": 30, "city": "Beijing"}
for key in person:
print(key)
for key, value in person.items():
print(f"{key}: {value}")
# 遍历范围
for i in range(5): # 0, 1, 2, 3, 4
print(i)
for i in range(2, 8): # 2, 3, 4, 5, 6, 7
print(i)
for i in range(0, 10, 2): # 0, 2, 4, 6, 8
print(i)
for i in range(10, 0, -1): # 10, 9, 8, ..., 1
print(i)
range 对象
range 不是列表,而是惰性序列,不占用额外内存:
r = range(1_000_000_000) # 不会占用大量内存
print(999_999 in r) # True — 支持 O(1) 的成员检测
print(r[500]) # 500 — 支持索引
print(len(r)) # 1000000000
嵌套循环
# 九九乘法表
for i in range(1, 10):
for j in range(1, i + 1):
print(f"{j}×{i}={i*j:2d}", end=" ")
print()
4.4 while 循环
# 基本 while
count = 0
while count < 5:
print(count)
count += 1
# 无限循环 + break
while True:
user_input = input("输入 q 退出: ")
if user_input == "q":
break
print(f"你输入了: {user_input}")
while 的典型场景
# 读取直到满足条件
lines = []
while (line := input("输入内容(空行结束): ")):
lines.append(line)
print(f"共输入 {len(lines)} 行")
# 数值迭代
n = 12345
digits = []
while n > 0:
digits.append(n % 10)
n //= 10
digits.reverse()
print(digits) # [1, 2, 3, 4, 5]
4.5 break、continue 与 else 子句
break — 立即退出循环
for i in range(100):
if i * i > 50:
print(f"第一个平方超过 50 的数: {i}")
break
# 输出: 第一个平方超过 50 的数: 8
continue — 跳过本次迭代
for i in range(10):
if i % 2 == 0:
continue # 跳过偶数
print(i)
# 输出: 1 3 5 7 9
else 子句 — 循环正常结束时执行
for...else 和 while...else 是 Python 独有的特性。else 块在循环没有被 break 中断时执行:
# 查找质数
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
break
else:
# 循环正常结束(没有 break),说明没有找到因数
return True
return False
print(is_prime(17)) # True
print(is_prime(15)) # False
# 搜索场景
target = 7
data = [1, 3, 5, 9, 11]
for item in data:
if item == target:
print(f"找到了 {target}")
break
else:
print(f"没有找到 {target}")
# 输出: 没有找到 7
可以把 for...else 理解为 “for…if-not-break”。
4.6 循环技巧
enumerate() — 同时获取索引和值
fruits = ["apple", "banana", "cherry"]
# 不推荐
for i in range(len(fruits)):
print(f"{i}: {fruits[i]}")
# 推荐
for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")
# 指定起始索引
for i, fruit in enumerate(fruits, start=1):
print(f"{i}. {fruit}")
# 1. apple
# 2. banana
# 3. cherry
zip() — 并行遍历多个序列
names = ["Alice", "Bob", "Charlie"]
ages = [30, 25, 35]
cities = ["Beijing", "Shanghai", "Shenzhen"]
for name, age, city in zip(names, ages, cities):
print(f"{name}, {age}岁, 来自{city}")
# zip 在最短序列耗尽时停止
list(zip([1, 2, 3], [4, 5])) # [(1, 4), (2, 5)]
# 如果需要匹配最长序列
from itertools import zip_longest
list(zip_longest([1, 2, 3], [4, 5], fillvalue=0))
# [(1, 4), (2, 5), (3, 0)]
zip 的妙用:
# 转置矩阵
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = list(zip(*matrix))
# [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
# 构建字典
keys = ["name", "age", "city"]
values = ["Alice", 30, "Beijing"]
person = dict(zip(keys, values))
# {'name': 'Alice', 'age': 30, 'city': 'Beijing'}
reversed() — 反向遍历
for i in reversed(range(5)):
print(i) # 4, 3, 2, 1, 0
# 反向遍历列表
for item in reversed([10, 20, 30]):
print(item) # 30, 20, 10
# 也可以用切片(但会创建新列表)
for item in [10, 20, 30][::-1]:
print(item)
sorted() — 排序遍历
colors = ["red", "blue", "green", "yellow"]
for color in sorted(colors):
print(color) # blue, green, red, yellow
for color in sorted(colors, reverse=True):
print(color) # yellow, red, green, blue
# 按长度排序
for color in sorted(colors, key=len):
print(color) # red, blue, green, yellow
# 对字典按值排序
scores = {"Alice": 90, "Bob": 75, "Charlie": 88}
for name, score in sorted(scores.items(), key=lambda x: x[1], reverse=True):
print(f"{name}: {score}")
# Alice: 90
# Charlie: 88
# Bob: 75
综合运用
# 带索引的排序遍历
students = ["Charlie", "Alice", "Bob"]
for rank, name in enumerate(sorted(students), start=1):
print(f"第{rank}名: {name}")
# 第1名: Alice
# 第2名: Bob
# 第3名: Charlie
本章小结:Python 的流程控制简洁而强大。
match-case模式匹配让复杂的条件分支变得优雅,for...else是独特的设计,enumerate、zip、sorted等内置函数让循环代码既简洁又 Pythonic。记住:Python 的 for 循环遍历的是可迭代对象,而非索引。