第5章:控制流
一、导读
1.1 本章学习目标
第5章讲解 Python 的控制流特性:生成器、上下文管理器、模式匹配、协程。
本章核心学习目标:
- 掌握生成器:yield 和生成器表达式
- 理解上下文管理器:with 语句和 __enter__/__exit__
- 掌握模式匹配:Python 3.10 的 match/case
- 了解协程:async/await 基础
1.2 为什么本章如此重要
生成器和上下文管理器是 Python 中最优雅的控制流工具。模式匹配让条件分支更清晰。
1.3 核心问题引导
yield 和 return 有什么区别?
上下文管理器如何保证资源释放?
模式匹配比 if/elif 有什么优势?
二、核心概念详解
2.1 生成器
python
# 生成器函数
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
print([next(fib) for _ in range(10)]) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
# 生成器表达式
squares = (x*x for x in range(10))
print(sum(squares)) # 285
# yield from: 委托给子生成器
def chain(*iterables):
for it in iterables:
yield from it
print(list(chain([1,2], [3,4], [5]))) # [1, 2, 3, 4, 5]
# 生成器的 send 方法
def accumulator():
total = 0
while True:
value = yield total
if value is None:
break
total += value
acc = accumulator()
next(acc) # 启动生成器
print(acc.send(10)) # 10
print(acc.send(20)) # 30
print(acc.send(30)) # 602.2 上下文管理器
python
import contextlib
# 类实现
class DatabaseConnection:
def __init__(self, connection_string):
self.conn_str = connection_string
self.conn = None
def __enter__(self):
print(f"Connecting to {self.conn_str}")
self.conn = "connected"
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Closing connection")
self.conn = None
return False # 不抑制异常
# @contextmanager 装饰器
@contextlib.contextmanager
def managed_resource(name):
print(f"Acquiring {name}")
try:
yield name
finally:
print(f"Releasing {name}")
with managed_resource("database") as r:
print(f"Using {r}")2.3 模式匹配
python
# Python 3.10+ 模式匹配
def describe_command(command):
match command.split():
case ["quit"]:
print("Goodbye!")
case ["go", direction]:
print(f"Going {direction}")
case ["drop", *items]:
print(f"Dropping: {', '.join(items)}")
case ["pick", "up", item]:
print(f"Picking up {item}")
case _:
print("Unknown command")
describe_command("go north") # Going north
describe_command("drop sword shield") # Dropping: sword, shield
# 结构化模式匹配
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
def where_is(point):
match point:
case Point(0, 0):
return "Origin"
case Point(0, y):
return f"On Y axis at {y}"
case Point(x, 0):
return f"On X axis at {x}"
case Point(x, y):
return f"At ({x}, {y})"
case _:
return "Not a point"三、实战案例
3.1 案例一:管道式数据处理
python
def read_lines(filename):
with open(filename) as f:
yield from f
def filter_comments(lines):
for line in lines:
if not line.startswith('#'):
yield line.strip()
def parse_csv(lines):
for line in lines:
yield line.split(',')
def transform(rows):
for row in rows:
yield {
'name': row[0],
'value': float(row[1]),
}
# 管道组合
def process(filename):
lines = read_lines(filename)
lines = filter_comments(lines)
rows = parse_csv(lines)
return transform(rows)四、本章小结
生成器通过 yield 实现惰性求值
上下文管理器通过 with 语句保证资源释放
模式匹配让复杂条件分支更清晰
五、思考与练习
生成器的 close() 和 throw() 方法有什么作用?
如何实现一个支持异步迭代的上下文管理器?