Python 进阶:生成器与上下文管理器

主题:生成器与上下文管理器

目标

  • 理解生成器的工作原理与 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,每行包含一些数据。我们需要对数据进行以下处理:

  1. 读取文件并去除空白字符。
  2. 过滤出满足条件的行(如长度大于 10 的行)。
  3. 对过滤后的行进行转换(如转为大写)。
  4. 将结果保存到新文件中。

实现步骤

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 语句管理资源,确保资源正确释放。
  • 生成器管道可以高效处理大文件,避免内存瓶颈。

五、课后练习

  1. 扩展生成器管道,增加更多处理阶段(如统计行数、计算平均值等)。
  2. 实现一个自定义上下文管理器,用于管理数据库连接。
  3. 使用协程实现一个简单的聊天服务器,支持多个客户端连接。

通过这些练习,进一步掌握生成器与上下文管理器的高级用法!

相关推荐
修复bug5 分钟前
Uniapp自定义TabBar组件全封装实践与疑难问题解决方案
前端·javascript·vue.js·uni-app·开源
qq_332539456 分钟前
自动化测试与 CAPTCHA 识别指南
javascript·爬虫·python·selenium·算法
Riesenzahn15 分钟前
为什么说css的选择器一般不要超过三级?
前端·javascript
喝西瓜汁的兔叽Yan16 分钟前
自定义指令--【v-lockScroll】用来锁定滚动条
前端
l_tian_tian_16 分钟前
JavaWeb——事务管理、AOP
java·开发语言
学渣y18 分钟前
React-响应事件
前端·javascript·react.js
高显20 分钟前
无参数读文件&RCE
python·安全
程序员的勇敢26 分钟前
告别付费!开箱即用,全网书源一键下载!
前端
zidea29 分钟前
deepseekers 一个面向 deepseek 的 AI Agent 框架(1)—结构化的输出
人工智能·python
风象南35 分钟前
SpringBoot全局异常处理的5种实现方式
java·spring boot·后端