主题:生成器与上下文管理器
目标
- 理解生成器的工作原理与 
yield表达式。 - 初步了解协程的概念与应用。
 - 学习如何实现自定义上下文管理器。
 - 通过生成器管道处理大文件。
 
一、生成器与 yield 表达式
1. 生成器的基本概念
生成器是一种特殊的迭代器,能够逐步生成数据,而不是一次性生成并存储所有数据。生成器函数使用 yield 关键字来返回值。
示例:
            
            
              python
              
              
            
          
          def my_generator():
    print("生成器开始执行")
    yield 1
    print("生成器继续执行")
    yield 2
    print("生成器结束执行")
# 使用生成器
g = my_generator()
print(next(g))  # 输出:1
print(next(g))  # 输出:2
        解释:
- 生成器函数 
my_generator使用yield返回值。 - 每次调用 
next()时,生成器从上次暂停的位置继续执行。 - 生成器的状态会被保留,直到生成器完成或抛出 
StopIteration。 
2. 生成器的优势
- 内存高效:生成器逐个生成数据,适合处理大数据或无限序列。
 - 惰性计算:只在需要时生成数据,避免不必要的计算。
 
示例:处理大文件
            
            
              python
              
              
            
          
          def read_file(filename):
    with open(filename, 'r') as f:
        for line in f:
            yield line.strip()
# 使用生成器处理大文件
for line in read_file('large_file.txt'):
    process(line)
        解释:
read_file是一个生成器函数,逐行读取文件内容。- 这种方式适合处理大文件,避免一次性将所有内容加载到内存。
 
3. 协程初步
协程(Coroutine)是一种高级的生成器,它不仅可以生成数据,还可以接收数据。协程通常用于实现高效的异步编程。
示例:简单的协程
            
            
              python
              
              
            
          
          def my_coroutine():
    print("协程开始")
    x = yield  # 接收外部发送的值
    print(f"接收到的值:{x}")
    print("协程结束")
# 使用协程
c = my_coroutine()
next(c)  # 启动协程
c.send(10)  # 发送值到协程
        输出:
协程开始
接收到的值:10
协程结束
        解释:
- 协程使用 
yield语句来接收外部发送的值。 - 需要先调用 
next()启动协程,然后使用send()发送数据。 
二、上下文管理器
1. 上下文管理器的基本概念
上下文管理器用于管理资源的生命周期(如文件、网络连接等),确保资源在使用后正确释放。常见的上下文管理器是 with 语句。
内置上下文管理器示例:
            
            
              python
              
              
            
          
          with open('file.txt', 'r') as f:
    # 文件在代码块结束时自动关闭
    content = f.read()
        自定义上下文管理器:
实现 __enter__ 和 __exit__ 方法。
示例:
            
            
              python
              
              
            
          
          class MyContextManager:
    def __enter__(self):
        print("进入上下文")
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("退出上下文")
        # 处理异常(可选)
        if exc_type is not None:
            print(f"捕获异常:{exc_type.__name__}")
        return True  # 返回 True 表示已处理异常
# 使用自定义上下文管理器
with MyContextManager():
    print("在上下文中执行代码")
        输出:
进入上下文
在上下文中执行代码
退出上下文
        2. 上下文管理器的应用场景
- 文件操作:自动关闭文件。
 - 锁管理:自动释放锁。
 - 数据库连接:自动关闭连接。
 
三、作业:处理大文件的生成器管道
目标
- 使用生成器构建一个处理大文件的管道。
 - 实现数据的分阶段处理,提高效率。
 
示例场景
假设有一个大文件 large_file.txt,每行包含一些数据。我们需要对数据进行以下处理:
- 读取文件并去除空白字符。
 - 过滤出满足条件的行(如长度大于 10 的行)。
 - 对过滤后的行进行转换(如转为大写)。
 - 将结果保存到新文件中。
 
实现步骤
1. 读取文件
            
            
              python
              
              
            
          
          def read_file(filename):
    """逐行读取文件内容"""
    with open(filename, 'r') as f:
        for line in f:
            yield line.strip()
        2. 过滤数据
            
            
              python
              
              
            
          
          def filter_lines(min_length=10):
    """过滤长度大于等于 min_length 的行"""
    while True:
        line = yield
        if len(line) >= min_length:
            yield line
        3. 转换数据
            
            
              python
              
              
            
          
          def convert_to_upper():
    """将行转换为大写"""
    while True:
        line = yield
        yield line.upper()
        4. 保存结果
            
            
              python
              
              
            
          
          def save_to_file(filename):
    """将结果保存到文件"""
    with open(filename, 'w') as f:
        while True:
            line = yield
            f.write(line + '\n')
        5. 构建管道
            
            
              python
              
              
            
          
          def pipeline():
    """构建生成器管道"""
    # 创建各阶段的生成器
    reader = read_file('large_file.txt')
    filterer = filter_lines()
    converter = convert_to_upper()
    saver = save_to_file('output.txt')
    # 启动生成器
    next(filterer)
    next(converter)
    next(saver)
    # 构建管道
    for line in reader:
        filterer.send(line)
        filtered_line = filterer.send(None)
        if filtered_line is not None:
            converter.send(filtered_line)
            upper_line = converter.send(None)
            saver.send(upper_line)
    # 关闭管道
    saver.send(None)
        6. 使用管道
            
            
              python
              
              
            
          
          if __name__ == '__main__':
    pipeline()
        解释
- 生成器管道 :通过 
send()方法将数据在各个生成器之间传递。 - 惰性处理:数据逐行处理,避免一次性加载大量数据到内存。
 - 模块化:每个阶段的功能独立,便于维护和扩展。
 
四、总结
- 生成器 通过 
yield表达式实现惰性计算与内存高效处理。 - 上下文管理器 通过 
with语句管理资源,确保资源正确释放。 - 生成器管道可以高效处理大文件,避免内存瓶颈。
 
五、课后练习
- 扩展生成器管道,增加更多处理阶段(如统计行数、计算平均值等)。
 - 实现一个自定义上下文管理器,用于管理数据库连接。
 - 使用协程实现一个简单的聊天服务器,支持多个客户端连接。
 
通过这些练习,进一步掌握生成器与上下文管理器的高级用法!