开启智能数字体验
Djacore CMS 驱动未来

基于Django 5.2的企业级智能内容管理系统,为千万级数据量设计, 提供安全、高效、可扩展的网站建设与内容管理一体化解决方案

Python yield 语法认识, yield的使用方法

:本站 2025-11-04 11:22:58 14

Python yield 语法认识, yield的使用方法

yield在这里确实是一个关键语法,它标志着上下文管理器的“执行分界线”。下面我用具体例子来详细解释。

yield的核心作用:执行分界线

简单来说,yield语句将你的上下文管理器函数(被 @contextmanager装饰的函数)分成了三个部分:

  1. yield之前的代码:相当于上下文管理器的 __enter__方法。在进入with语句块之前执行,通常负责准备工作,比如获取资源、记录初始状态。在你的代码中,就是 start = time.perf_counter()

  2. yield语句本身:它是一个暂停点。程序执行到这里会暂停,并将 yield后面的值(如果有)返回给 with语句中 as关键字指定的变量。在你的代码中,yield后面没有值,所以不返回资源,只是暂停。

  3. yield之后的代码:相当于上下文管理器的 __exit__方法。在退出with语句块之后执行,无论块内的代码是正常结束还是发生异常都会执行(这得益于 try...finally结构)。通常负责清理工作,比如释放资源、记录结束状态。在你的代码中,就是计算并打印耗时。

整个执行流程,以及 yield如何作为分界线,可以用下表清晰地展示:

步骤

对应代码

执行时机与功能

1. 进入上下文

start = time.perf_counter()

进入with之前执行,记录开始时间。

2. 执行 with块内代码

yieldtime.sleep(0.5)

yield处暂停,将执行权交给 with块内的代码。

3. 退出上下文

end = ...print(...)

退出with之后执行,计算并打印耗时。

扩展示例:让 yield传递资源

yield的一个强大之处在于它可以with代码块内传递一个资源或对象,并在块内代码执行完毕后确保该资源被正确清理。下面看几个具体的例子。

1. 自动管理文件操作状态

这个例子模拟一个数据处理任务,yield传递一个状态字典,用于在 with块内外记录信息。

from contextlib import contextmanager
import time

@contextmanager
def managed_data_processor(operation_name):
    # 进入with块前:准备工作 (相当于 __enter__)
    start_time = time.perf_counter()
    status = {"operation": operation_name, "start_time": start_time, "success": False}
    
    print(f"[{operation_name}] 开始处理...")
    
    try:
        # yield 传递status字典到with块内,并暂停执行
        yield status
        # 如果with块内代码正常执行完毕,回到这里,标记成功
        status["success"] = True
        
    except Exception as e:
        # 如果with块内发生异常,也会回到这里
        status["error"] = str(e)
        print(f"[{operation_name}] 处理出错: {e}")
        # 异常会被继续抛出,除非这里return True
        raise
    finally:
        # 退出with块后:清理工作 (相当于 __exit__)
        end_time = time.perf_counter()
        duration = end_time - start_time
        status["end_time"] = end_time
        status["duration"] = duration
        
        if status.get("success"):
            print(f"[{operation_name}] 处理成功!耗时: {duration:.4f}秒")
        else:
            print(f"[{operation_name}] 处理失败!耗时: {duration:.4f}秒")

# 使用示例
with managed_data_processor("数据导入") as proc_status:
    # 这里可以操作yield传出的status字典
    proc_status["rows_processed"] = 1000
    # 模拟一个耗时操作
    time.sleep(0.5)
    # 可以取消下一行的注释来模拟异常情况
    # raise ValueError("模拟一个错误")

输出(正常情况):

[数据导入] 开始处理...
[数据导入] 处理成功!耗时: 0.5001秒

输出(有异常时):

[数据导入] 开始处理...
[数据导入] 处理出错: 模拟一个错误
[数据导入] 处理失败!耗时: 0.0002秒
Traceback (most recent call last):
  ...

2. 临时切换工作目录(并确保切回)

这个例子展示了如何使用 yield管理一个“状态”而不是一个具体的“资源”,并在最后确保状态恢复。

from contextlib import contextmanager
import os

@contextmanager
def temporary_cd(new_dir):
    # 进入with块前:保存当前目录
    original_dir = os.getcwd()
    os.chdir(new_dir)
    print(f"已切换到目录: {os.getcwd()}")
    
    try:
        # yield 之前已切换目录,此处不传递值,只是暂停
        yield
        # with块内代码执行完毕后,会回到这里
    finally:
        # 退出with块后:无论是否异常,都切回原目录
        os.chdir(original_dir)
        print(f"已切换回目录: {os.getcwd()}")

# 使用示例
print(f"起始目录: {os.getcwd()}")

with temporary_cd("/tmp"): # 假设/tmp目录存在
    # 在这个块内,当前工作目录是 /tmp
    print(f"块内当前目录: {os.getcwd()}")
    # 可以在这里进行一些只在/tmp目录下的操作,比如创建临时文件
    with open("tempfile.txt", "w") as f:
        f.write("hello")

# 退出with块后,目录自动切回起始目录
print(f"结束目录: {os.getcwd()}")

总结

  • yield是一个关键词:它是 Python 中用于定义生成器或(配合 @contextmanager)创建上下文管理器的核心语法。

  • yield是指一个“操作节点”:它代表了执行流程的暂停和恢复点,将代码逻辑清晰地划分为“进入时准备”、“内部执行”和“退出时清理”三个阶段。

  • yield可以传递数据:通过 yield resource,你可以将资源(如文件对象、数据库连接、状态字典)安全地传递给 with块内的代码使用,并保证后续的清理工作。

这种模式极大地简化了资源管理代码,使其更安全、更清晰、更符合 Python 的优雅风格。

本文编辑:admin

更多文章:


Python yield 语法认识, yield的使用方法

Python yield 语法认识, yield的使用方法

yield在这里确实是一个关键语法,它标志着上下文管理器的“执行分界线”。下面我用具体例子来详细解释。yield的核心作用:执行分界线简单来说,yield语句将你的上下文管理器函数(被 @contextmanager装饰的函数)分成了三个部

2025年11月4日 11:22

python with的原理,python with 在django框架当中有哪些优秀用法

python with的原理,python with 在django框架当中有哪些优秀用法

with语句是 Python 中用于简化资源管理的强大工具,下面详细解释其原理、用法、常见应用场景及其在 Django 框架中的优秀实践。Python with语句详解1. with语句的基本原理with语句基于上下文管理器协议(Conte

2025年11月4日 11:15

Python操作数据库方法总结,Python如何高效的进行数据库交互

Python操作数据库方法总结,Python如何高效的进行数据库交互

在Python中操作数据库确实涉及一系列标准且重要的方法。掌握这些方法能让你高效且安全地与数据库进行交互。下面这个表格汇总了这些核心方法,方便你快速建立整体概念。方法类别方法名称功能描述连接与游标connect()建立与数据库的连接,是一切

2025年11月3日 23:23

最近更新

使用DRF快速搭建API接口,Django REST Framework ModelViewSet 用法总结
2026-03-01 09:10:09 浏览:4
宝塔Nginx免费防火墙常用UA防护正则
2026-01-20 00:53:21 浏览:38
django 使用selenium注意事项:Service /usr/local/bin/chromedriver unexpectedly exited. Status code was: 1解决办法
2026-01-06 00:58:37 浏览:10
Django移除模型后的content_type操作
2025-12-22 11:36:29 浏览:6
热门文章

DjancoreCMS打包前操作
2025-05-26 17:58:05 浏览:81
宝塔Nginx免费防火墙常用UA防护正则
2026-01-20 00:53:21 浏览:38
标签列表