5Fluent Python(第2版)

控制流

流程控制

生成器上下文管理器模式匹配协程

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第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))  # 60

2.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() 方法有什么作用?

如何实现一个支持异步迭代的上下文管理器?


5/8控制流
0%