第4章 流程控制
学习目标
完成本章学习后,读者将能够:
- 掌握条件语句的完整语法体系,包括模式匹配(match-case)
- 理解Python循环机制的底层原理与迭代协议
- 熟练运用推导式(Comprehension)编写简洁高效的数据转换代码
- 掌握break、continue、else子句的精确语义
- 理解生成器表达式的惰性求值特性及其内存优势
4.1 条件语句
4.1.1 if语句
age = 18
if age >= 18:
print("成年人")
score = 85
if score >= 60:
print("及格")
print("恭喜!")4.1.2 if-else语句
age = 16
if age >= 18:
print("成年人")
else:
print("未成年人")
number = 7
print("偶数" if number % 2 == 0 else "奇数")4.1.3 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}")学术注记:Python的
elif是else if的缩写,避免了C/Java中深层嵌套的}链。Python没有switch-case语句(3.10之前),传统上使用if-elif链或字典分派模式替代。
4.1.4 条件表达式(三元运算符)
age = 20
status = "成年人" if age >= 18 else "未成年人"
x, y = 10, 20
max_value = x if x > y else y
# 链式条件表达式(可读性差,不推荐超过两层)
score = 85
grade = (
"A" if score >= 90 else
"B" if score >= 80 else
"C" if score >= 70 else
"D" if score >= 60 else
"F"
)4.1.5 逻辑运算符组合条件
age = 25
has_license = True
if age >= 18 and has_license:
print("可以驾驶")
if age < 18 or not has_license:
print("不能驾驶")
# Pythonic:链式比较
if 18 <= age <= 30:
print("年龄在18到30之间")
# 成员测试
if char in "aeiou":
print("元音字母")4.1.6 模式匹配(Python 3.10+)
PEP 634引入的结构模式匹配是Python 3.10最重要的新特性之一:
# 字面量模式
def http_status(status: int) -> str:
match status:
case 200:
return "OK"
case 301:
return "Moved Permanently"
case 400:
return "Bad Request"
case 404:
return "Not Found"
case 500:
return "Internal Server Error"
case _:
return "Unknown Status"
# 序列模式——解构与捕获
def process_command(command: str) -> str:
match command.split():
case ["quit"]:
return "退出程序"
case ["hello", name]:
return f"你好,{name}!"
case ["add", x, y]:
return f"结果:{int(x) + int(y)}"
case ["list", *items]:
return f"列表:{items}"
case _:
return "未知命令"
# 映射模式——字典解构
def handle_event(event: dict) -> str:
match event:
case {"type": "click", "x": x, "y": y}:
return f"点击位置:({x}, {y})"
case {"type": "key", "key": key}:
return f"按键:{key}"
case {"type": "scroll", "delta": delta} if delta > 0:
return "向上滚动"
case {"type": "scroll"}:
return "向下滚动"
case _:
return "未知事件"
# 类模式——对象解构
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
def describe_point(point: Point) -> str:
match point:
case Point(x=0, y=0):
return "原点"
case Point(x=0, y=y):
return f"Y轴上,y={y}"
case Point(x=x, y=0):
return f"X轴上,x={x}"
case Point(x=x, y=y):
return f"坐标({x}, {y})"
# OR模式与守卫条件
def classify(value: int) -> str:
match value:
case 0 | 1:
return "二进制位"
case n if n < 0:
return "负数"
case n if n > 100:
return "大数"
case _:
return "普通正数"学术注记:模式匹配源自函数式编程语言(Haskell、Scala、Rust),其核心思想是声明式的——描述"数据的形状"而非"如何提取数据"。相比
if-elif链,模式匹配将数据解构与条件判断合二为一,显著减少了样板代码。
4.2 循环语句
4.2.1 while循环
count = 0
while count < 5:
print(count)
count += 1
# 经典算法:数字反转
number = 12345
reversed_num = 0
while number > 0:
digit = number % 10
reversed_num = reversed_num * 10 + digit
number //= 10
print(f"反转:{reversed_num}") # 54321
# 欧几里得算法:最大公约数
def gcd(a: int, b: int) -> int:
while b:
a, b = b, a % b
return a4.2.2 for循环与迭代协议
Python的for循环不基于索引,而是基于迭代协议(Iterator Protocol):
# 迭代可迭代对象
for fruit in ["apple", "banana", "cherry"]:
print(fruit)
for char in "Python":
print(char)
for key, value in {"name": "Alice", "age": 25}.items():
print(f"{key}: {value}")
# range详解
for i in range(5): # 0, 1, 2, 3, 4
print(i)
for i in range(1, 6): # 1, 2, 3, 4, 5
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)
# enumerate:带索引迭代
fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits, start=1):
print(f"{index}: {fruit}")
# zip:并行迭代
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
for name, age in zip(names, ages):
print(f"{name}, {age}岁")
# zip不等长时以最短为准
from itertools import zip_longest
for item in zip_longest([1, 2, 3], [4, 5], fillvalue=0):
print(item) # (1, 4), (2, 5), (3, 0)学术注记:Python的
for循环本质是调用iter()获取迭代器,然后反复调用__next__()直到StopIteration异常。这意味着任何实现了__iter__()和__next__()的对象都可以用于for循环。range对象是惰性求值的,不会一次性生成所有数字,因此range(10**9)不会消耗大量内存。
4.2.3 循环的else子句
Python循环支持else子句,其语义是:循环正常结束(未被break中断)时执行else块:
# 查找质数
def is_prime(n: int) -> bool:
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
break
else:
return True
return False
# 等价写法(更易读)
def is_prime_v2(n: int) -> bool:
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
return True工程实践:循环的
else子句是Python中容易混淆的语法特性。在简单场景中,使用return提前退出往往比for-else更清晰。for-else最适合的场景是"查找-未找到"模式。
4.2.4 循环嵌套
# 九九乘法表
for i in range(1, 10):
for j in range(1, i + 1):
print(f"{j}×{i}={i*j}", end=" ")
print()
# 矩阵遍历
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
for row in matrix:
for item in row:
print(item, end=" ")
print()
# 对角线遍历
for i in range(len(matrix)):
print(matrix[i][i], end=" ")
print()4.3 循环控制
4.3.1 break——提前终止循环
for i in range(10):
if i == 5:
break
print(i) # 0, 1, 2, 3, 4
# 实用:查找第一个满足条件的元素
def find_first_even(numbers: list) -> int | None:
for num in numbers:
if num % 2 == 0:
return num
return None
# 注意:break只跳出最内层循环
for i in range(3):
for j in range(3):
if i == 1 and j == 1:
break # 只跳出内层循环
print(f"({i}, {j})")4.3.2 continue——跳过当前迭代
# 只打印奇数
for i in range(10):
if i % 2 == 0:
continue
print(i) # 1, 3, 5, 7, 9
# 过滤无效数据
records = [{"name": "Alice", "age": 25}, None, {"name": "Bob", "age": 30}]
for record in records:
if record is None:
continue
print(f"{record['name']}: {record['age']}岁")4.3.3 pass——空操作占位
# 占位:待实现
class MyError(Exception):
pass
def todo_function():
pass
# pass vs ...(Ellipsis)
def todo_function():
... # 等价于pass,某些团队偏好此写法4.4 推导式
推导式(Comprehension)是Python最具特色的语法之一,将循环与条件判断浓缩为简洁的表达式。
4.4.1 列表推导式
# 基本形式:[表达式 for 变量 in 可迭代对象]
squares = [x ** 2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 带条件过滤:[表达式 for 变量 in 可迭代对象 if 条件]
evens = [x for x in range(20) if x % 2 == 0]
# 带条件表达式:[表达式1 if 条件 else 表达式2 for 变量 in 可迭代对象]
labels = ["偶数" if x % 2 == 0 else "奇数" for x in range(5)]
# 嵌套循环
pairs = [(x, y) for x in range(3) for y in range(3)]
# 多层推导式(矩阵转置)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = [[row[i] for row in matrix] for i in range(3)]
# 扁平化嵌套列表
flattened = [num for row in matrix for num in row]4.4.2 字典推导式
# 基本形式:{键表达式: 值表达式 for 变量 in 可迭代对象}
squares = {x: x ** 2 for x in range(5)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# 从两个列表创建字典
keys = ["name", "age", "city"]
values = ["Alice", 25, "北京"]
person = {k: v for k, v in zip(keys, values)}
# 过滤
scores = {"Alice": 85, "Bob": 72, "Charlie": 92, "David": 65}
passed = {name: score for name, score in scores.items() if score >= 80}
# 字符频率统计
text = "hello world"
freq = {char: text.count(char) for char in set(text)}4.4.3 集合推导式
# 基本形式:{表达式 for 变量 in 可迭代对象}
squares = {x ** 2 for x in range(-5, 6)}
print(squares) # {0, 1, 4, 9, 16, 25} - 自动去重
# 提取唯一元音
text = "Hello World"
vowels = {char.lower() for char in text if char.lower() in "aeiou"}
print(vowels) # {'e', 'o'}4.4.4 生成器表达式
生成器表达式使用圆括号,惰性求值,不一次性生成所有结果:
# 列表推导式:立即计算,占用内存
squares_list = [x ** 2 for x in range(10)]
# 生成器表达式:惰性计算,节省内存
squares_gen = (x ** 2 for x in range(10))
print(type(squares_gen)) # <class 'generator'>
# 逐个获取值
print(next(squares_gen)) # 0
print(next(squares_gen)) # 1
# 配合聚合函数使用(最常见场景)
total = sum(x ** 2 for x in range(100))
maximum = max(x ** 2 for x in range(100))
has_any = any(x < 0 for x in [1, 2, 3])
all_positive = all(x > 0 for x in [1, 2, 3])
# 内存对比
import sys
list_comp = [x ** 2 for x in range(10000)]
gen_expr = (x ** 2 for x in range(10000))
print(sys.getsizeof(list_comp)) # ~87616 字节
print(sys.getsizeof(gen_expr)) # ~200 字节工程实践:当结果只需迭代一次(如传入
sum()、max()、any()等函数),优先使用生成器表达式而非列表推导式。当需要多次迭代或索引访问时,使用列表推导式。
4.5 迭代工具
4.5.1 itertools模块
from itertools import count, cycle, repeat, chain, islice, groupby, product, permutations, combinations
# 无限迭代器
for i in islice(count(10, 2), 5): # 从10开始,步长2,取5个
print(i) # 10, 12, 14, 16, 18
# 链接多个可迭代对象
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
for item in chain(list1, list2):
print(item)
# 排列组合
print(list(permutations('ABC', 2))) # [('A','B'), ('A','C'), ('B','A'), ...]
print(list(combinations('ABC', 2))) # [('A','B'), ('A','C'), ('B','C')]
print(list(product('AB', '12'))) # [('A','1'), ('A','2'), ('B','1'), ('B','2')]
# 分组
data = [('A', 1), ('A', 2), ('B', 3), ('B', 4)]
for key, group in groupby(data, key=lambda x: x[0]):
print(f"{key}: {list(group)}")4.5.2 实用迭代模式
# 反向迭代
for i in reversed(range(5)):
print(i) # 4, 3, 2, 1, 0
# 排序迭代
students = [{"name": "Alice", "score": 85}, {"name": "Bob", "score": 92}]
for s in sorted(students, key=lambda x: x["score"], reverse=True):
print(s)
# 字典安全迭代中修改
d = {"a": 1, "b": 2, "c": 3}
for key in list(d.keys()):
if d[key] < 2:
del d[key]4.6 算法思维训练
4.6.1 经典算法实现
二分查找
def binary_search(arr: list, target: int) -> int | None:
"""二分查找:O(log n)时间复杂度"""
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return None
sorted_list = [1, 3, 5, 7, 9, 11, 13, 15]
print(binary_search(sorted_list, 7)) # 3
print(binary_search(sorted_list, 8)) # None冒泡排序
def bubble_sort(arr: list) -> list:
"""冒泡排序:O(n²)时间复杂度"""
n = len(arr)
for i in range(n):
swapped = False
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
swapped = True
if not swapped:
break
return arr
print(bubble_sort([64, 34, 25, 12, 22, 11, 90]))快速排序
def quick_sort(arr: list) -> list:
"""快速排序:平均O(n log n)"""
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quick_sort(left) + middle + quick_sort(right)
print(quick_sort([3, 6, 8, 10, 1, 2, 1]))斐波那契数列
def fibonacci_iterative(n: int) -> list:
"""迭代法:O(n)时间,O(n)空间"""
if n <= 0:
return []
if n == 1:
return [0]
fib = [0, 1]
for i in range(2, n):
fib.append(fib[i-1] + fib[i-2])
return fib
def fibonacci_generator():
"""生成器版本:无限序列"""
a, b = 0, 1
while True:
yield a
a, b = b, a + b
from itertools import islice
print(list(islice(fibonacci_generator(), 10)))4.6.2 循环优化技巧
避免在循环内重复计算
import time
def slow_version(n: int) -> list:
result = []
for i in range(n):
result.append(i * 3.14159 ** 2)
return result
def fast_version(n: int) -> list:
pi_squared = 3.14159 ** 2
return [i * pi_squared for i in range(n)]
n = 1_000_000
start = time.time()
slow_version(n)
print(f"慢版本: {time.time() - start:.3f}秒")
start = time.time()
fast_version(n)
print(f"快版本: {time.time() - start:.3f}秒")使用内置函数替代循环
import time
data = list(range(1_000_000))
start = time.time()
total = 0
for x in data:
total += x
print(f"循环求和: {time.time() - start:.4f}秒")
start = time.time()
total = sum(data)
print(f"内置sum: {time.time() - start:.4f}秒")
start = time.time()
squared = []
for x in data:
squared.append(x ** 2)
print(f"循环平方: {time.time() - start:.4f}秒")
start = time.time()
squared = [x ** 2 for x in data]
print(f"推导式: {time.time() - start:.4f}秒")提前退出优化
def find_target_slow(data: list, target: int) -> bool:
"""遍历全部元素"""
found = False
for item in data:
if item == target:
found = True
return found
def find_target_fast(data: list, target: int) -> bool:
"""找到即退出"""
for item in data:
if item == target:
return True
return False
def find_target_pythonic(data: list, target: int) -> bool:
"""Pythonic方式"""
return target in data4.6.3 时间复杂度分析
def analyze_complexity():
"""常见循环模式的时间复杂度"""
# O(n) - 单层循环
def o_n(n):
for i in range(n):
pass
# O(n²) - 嵌套循环
def o_n_squared(n):
for i in range(n):
for j in range(n):
pass
# O(log n) - 对数循环
def o_log_n(n):
i = 1
while i < n:
i *= 2
# O(n log n) - 线性对数
def o_n_log_n(n):
for i in range(n):
j = 1
while j < n:
j *= 2
# O(√n) - 平方根循环
def o_sqrt_n(n):
i = 1
while i * i < n:
i += 1
analyze_complexity()| 复杂度 | 名称 | 示例 | n=1000时操作数 |
|---|---|---|---|
| O(1) | 常数 | 数组索引 | 1 |
| O(log n) | 对数 | 二分查找 | 10 |
| O(√n) | 平方根 | 质数判断 | 32 |
| O(n) | 线性 | 单层循环 | 1000 |
| O(n log n) | 线性对数 | 快速排序 | 10000 |
| O(n²) | 平方 | 嵌套循环 | 1000000 |
| O(2ⁿ) | 指数 | 递归斐波那契 | 10³⁰¹ |
4.7 前沿技术动态
4.7.1 结构化模式匹配(PEP 634)
Python 3.10引入的模式匹配提供了强大的控制流表达能力:
def process_event(event: dict) -> str:
match event:
case {"type": "login", "user": str(name)}:
return f"User {name} logged in"
case {"type": "logout", "user": str(name), "reason": reason}:
return f"User {name} logged out: {reason}"
case {"type": "error", "code": code} if code >= 500:
return f"Server error: {code}"
case {"type": "error", "code": code}:
return f"Client error: {code}"
case _:
return "Unknown event"4.7.2 异步迭代与循环
现代Python支持异步迭代器和异步for循环:
import asyncio
async def async_count(n: int):
for i in range(n):
await asyncio.sleep(0.1)
yield i
async def main():
async for num in async_count(5):
print(num)
async for num in async_count(3):
if num == 1:
continue
print(f"Got: {num}")
asyncio.run(main())4.7.3 性能优化技术
import itertools
# 使用itertools替代显式循环
data = range(1000000)
sum_result = sum(data)
any_positive = any(x > 0 for x in data)
all_positive = all(x >= 0 for x in data)
first_ten = itertools.islice(data, 10)
chunked = iter(lambda: list(itertools.islice(data, 100)), [])4.7.4 循环展开与向量化
import numpy as np
data = list(range(1000000))
result_loop = [x * 2 + 1 for x in data]
arr = np.array(data)
result_vectorized = arr * 2 + 14.8 本章小结
本章系统介绍了Python流程控制的完整体系:
- 条件语句:if-elif-else、条件表达式、模式匹配(3.10+)
- 循环机制:while循环、for循环基于迭代协议、循环的else子句
- 循环控制:break终止、continue跳过、pass占位
- 推导式:列表、字典、集合推导式——声明式数据转换
- 生成器表达式:惰性求值,内存友好的迭代方式
- 迭代工具:enumerate、zip、itertools模块
- 算法思维:经典算法实现、循环优化、时间复杂度分析
4.8.1 流程控制选择指南
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 简单条件判断 | if-elif-else | 清晰直观 |
| 多分支字面量匹配 | match-case (3.10+) | 声明式,支持解构 |
| 已知次数循环 | for + range | 明确迭代范围 |
| 条件驱动循环 | while | 条件终止 |
| 数据转换 | 推导式 | 简洁高效 |
| 大数据聚合 | 生成器表达式 | 内存友好 |
| 查找后处理 | for-else | 未找到时执行 |
4.8.2 性能优化清单
- 优先使用内置函数:
sum()、max()、any()比循环快 - 推导式优于append循环:列表推导式比循环append快约30%
- 生成器处理大数据:避免一次性加载全部数据到内存
- 提前退出:找到目标后立即
break或return - 循环外提:将不变计算移出循环
- 避免重复计算:缓存循环中重复使用的值
4.9 知识图谱
4.9.1 Python流程控制体系
Python流程控制结构
├── 条件语句
│ ├── if 语句
│ ├── if-else 语句
│ ├── if-elif-else 语句
│ ├── 条件表达式(三元运算符)
│ └── match-case 模式匹配 (3.10+)
│ ├── 字面量模式
│ ├── 序列模式
│ ├── 映射模式
│ ├── 类模式
│ └── OR模式与守卫
├── 循环语句
│ ├── while 循环
│ ├── for 循环(迭代协议)
│ ├── 循环的 else 子句
│ └── 循环嵌套
├── 循环控制
│ ├── break(终止循环)
│ ├── continue(跳过迭代)
│ └── pass(空操作占位)
└── 推导式
├── 列表推导式
├── 字典推导式
├── 集合推导式
└── 生成器表达式4.9.2 迭代协议流程图
for item in iterable:
└── 调用 iter(iterable)
│
▼
┌───────────────────┐
│ 获取迭代器对象 │
│ iterator = iter() │
└───────────────────┘
│
▼
┌───────────────────┐
│ 调用 next() │◄─────┐
│ item = next(it) │ │
└───────────────────┘ │
│ │
▼ │
┌───────────────────┐ │
│ StopIteration? │──否──┘
│ 是 → 结束循环 │
└───────────────────┘
│
▼
执行循环体4.9.3 推导式性能对比
数据规模: 1,000,000 个元素
┌─────────────────────────────────────────────────────────┐
│ 方法 │ 时间 │ 内存 │ 推荐度 │
├─────────────────────────────────────────────────────────┤
│ 列表推导式 │ 0.15s │ 8MB │ ★★★★★ │
│ for循环 + append │ 0.20s │ 8MB │ ★★★★☆ │
│ map() + list() │ 0.18s │ 8MB │ ★★★☆☆ │
│ 生成器表达式 + list() │ 0.16s │ 8MB │ ★★★★☆ │
│ 生成器表达式(惰性) │ 0.001s │ 200B │ ★★★★★ │
└─────────────────────────────────────────────────────────┘4.10 技术选型指南
4.10.1 条件语句选型
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 简单二选一 | if-else | 清晰直观 |
| 多分支值匹配 | match-case (3.10+) | 声明式,支持解构 |
| 多分支条件判断 | if-elif-else | 灵活,任意条件 |
| 单行赋值 | 条件表达式 | 简洁 |
| 复杂条件组合 | 提前return | 减少嵌套 |
4.10.2 循环语句选型
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 已知迭代次数 | for + range | 明确范围 |
| 遍历集合 | for item in collection | Pythonic |
| 条件驱动 | while | 动态终止条件 |
| 带索引遍历 | enumerate() | 同时获取索引和值 |
| 并行遍历 | zip() | 多序列同步 |
| 无限序列 | itertools.count/cycle | 惰性生成 |
4.10.3 数据转换选型
| 场景 | 推荐方案 | 内存 | 性能 |
|---|---|---|---|
| 需要多次访问 | 列表推导式 | 高 | 快 |
| 单次遍历聚合 | 生成器表达式 | 低 | 中 |
| 创建字典 | 字典推导式 | 中 | 快 |
| 去重转换 | 集合推导式 | 中 | 快 |
| 链式操作 | 生成器 + itertools | 低 | 中 |
4.10.4 itertools常用函数速查
from itertools import (
count, cycle, repeat, # 无限迭代器
chain, compress, dropwhile, takewhile, # 迭代器操作
islice, starmap, # 切片与映射
groupby, # 分组
product, permutations, combinations, combinations_with_replacement, # 排列组合
)
# 实用示例
list(chain([1,2], [3,4])) # [1,2,3,4]
list(islice(count(10), 5)) # [10,11,12,13,14]
list(combinations('ABC', 2)) # [('A','B'), ('A','C'), ('B','C')]
list(product('AB', repeat=2)) # [('A','A'), ('A','B'), ('B','A'), ('B','B')]4.11 常见问题与解决方案
4.11.1 循环中的变量作用域
# 问题:循环变量在循环后仍然存在
for i in range(5):
pass
print(i) # 4 - 变量未销毁
# 解决方案:使用生成器表达式或函数封装
def process():
for i in range(5):
pass
# i 在函数作用域内
process()
# print(i) # NameError4.11.2 修改迭代中的集合
# 问题:遍历时修改列表导致意外行为
items = [1, 2, 3, 4, 5]
for item in items:
if item % 2 == 0:
items.remove(item) # 危险!可能跳过元素
# 解决方案1:遍历副本
items = [1, 2, 3, 4, 5]
for item in items[:]: # 切片创建副本
if item % 2 == 0:
items.remove(item)
# 解决方案2:列表推导式
items = [item for item in items if item % 2 != 0]
# 解决方案3:使用filter
items = list(filter(lambda x: x % 2 != 0, items))4.11.3 无限循环陷阱
# 问题:忘记更新循环条件
i = 0
while i < 10:
print(i)
# 忘记 i += 1,导致无限循环
# 解决方案:使用for循环或确保更新条件
for i in range(10):
print(i)
# 或添加超时机制
import time
start = time.time()
while condition:
if time.time() - start > 10: # 10秒超时
break
# 处理逻辑4.11.4 模式匹配陷阱
# 问题:模式匹配中的变量绑定
match [1, 2, 3]:
case [x, y, z]:
print(x, y, z) # 1 2 3
case [x, *rest]:
print(x, rest) # 不会执行,因为上面的模式已匹配
# 解决方案:注意模式顺序,更具体的模式放前面
match [1, 2, 3]:
case [x, *rest]:
print(x, rest) # 1 [2, 3]
case [x, y, z]:
print(x, y, z)
# 问题:使用守卫条件
match 5:
case n if n > 10:
print("大数")
case n if n > 0:
print("正数") # 匹配这里
case _:
print("其他")4.11.5 生成器耗尽问题
# 问题:生成器只能迭代一次
gen = (x ** 2 for x in range(5))
print(list(gen)) # [0, 1, 4, 9, 16]
print(list(gen)) # [] - 已耗尽!
# 解决方案1:重新创建生成器
def squares(n):
return (x ** 2 for x in range(n))
gen1 = squares(5)
gen2 = squares(5)
# 解决方案2:使用itertools.tee
from itertools import tee
gen = (x ** 2 for x in range(5))
gen1, gen2 = tee(gen)
print(list(gen1)) # [0, 1, 4, 9, 16]
print(list(gen2)) # [0, 1, 4, 9, 16]
# 解决方案3:转换为列表(如果数据量不大)
data = list(x ** 2 for x in range(5))4.12 练习题
基础题
编写程序,判断一个年份是否为闰年(能被4整除但不能被100整除,或能被400整除)。
使用for循环打印九九乘法表,格式整齐。
使用列表推导式生成1-100中所有能被3整除但不能被5整除的数。
进阶题
找出100-999之间的所有水仙花数(各位数字的立方和等于该数本身),如153=1³+5³+3³。
使用模式匹配实现一个简易计算器,支持
add、sub、mul、div命令。编写函数,使用生成器表达式实现一个内存高效的大文件行过滤器。
项目实践
- 学生成绩管理系统:编写一个命令行程序,要求:
- 使用字典存储学生姓名和成绩
- 支持添加、删除、查询、统计操作
- 使用match-case处理命令
- 使用推导式进行数据过滤和统计
- 支持按成绩排序输出
思考题
Python的
for循环与C语言的for循环在语义上有何本质区别?迭代协议带来了哪些优势?列表推导式
[x for x in range(n) if condition]与等价的for循环在性能上有差异吗?为什么?循环的
else子句为什么被认为是Python中"令人困惑"的特性?在实际项目中,你倾向于使用for-else还是替代方案?
4.13 延伸阅读
4.13.1 算法与数据结构
- 《算法导论》 (CLRS) — 算法领域的权威教材,深入讲解时间复杂度分析和经典算法
- 《算法(第4版)》 (Robert Sedgewick) — Java实现但算法思想通用,配图丰富易于理解
- LeetCode (https://leetcode.cn/) — 在线算法练习平台,通过实战提升算法能力
- VisuAlgo (https://visualgo.net/) — 算法可视化工具,帮助理解算法执行过程
4.13.2 Python迭代机制
- PEP 255 — Simple Generators (https://peps.python.org/pep-0255/) — 生成器的原始提案
- PEP 634 — Structural Pattern Matching (https://peps.python.org/pep-0634/) — 模式匹配的官方规范
- itertools模块文档 (https://docs.python.org/3/library/itertools.html) — Python迭代工具的完整参考
- **《Fluent Python》第14章》 — 深入讲解可迭代对象、迭代器和生成器
4.13.3 性能优化
- 《High Performance Python》 (Micha Gorelick & Ian Ozsvald) — Python性能优化的权威指南
- Python性能分析工具 —
cProfile、line_profiler、memory_profiler - TimeComplexity — Python Wiki (https://wiki.python.org/moin/TimeComplexity) — Python内置操作的时间复杂度参考
4.13.4 函数式编程
- 《Functional Programming in Python》 (David Mertz) — Python中的函数式编程技术
- fn.py (https://github.com/kachayev/fn.py) — Python函数式编程增强库
- toolz (https://github.com/pytoolz/toolz) — 函数式编程工具集,提供高效的迭代器操作
下一章:第5章 函数与模块