gpt4 book ai didi

python - yield without value 在上下文管理器中做什么

转载 作者:太空狗 更新时间:2023-10-29 18:00:06 26 4
gpt4 key购买 nike

import contextlib
import time

@contextlib.contextmanager
def time_print(task_name):
t = time.time()
try:
yield
finally:
print task_name, "took", time.time() - t, "seconds."


def doproc():
x=1+1


with time_print("processes"):
[doproc() for _ in range(500)]

# processes took 15.236166954 seconds.

使用这个装饰器时doproc什么时候执行?

最佳答案

yield 表达式将控制权返回给使用生成器的任何对象。生成器在此时暂停,这意味着 @contextmanager 装饰器知道代码已完成 setup 部分。

换句话说,你想在上下文管理器 __enter__ 阶段做的所有事情都必须在 yield 之前发生。

一旦您的上下文退出(因此 with 语句下的 block 完成),@contextmanager 装饰器将被调用用于 __exit__ 部分上下文管理器协议(protocol),并将做两件事之一:

  • 如果没有异常,它将恢复您的生成器。所以你的生成器在 yield 行取消暂停,然后你进入清理阶段,部分

  • 如果出现异常,装饰器会使用 generator.throw() 在生成器中引发该异常。就好像 yield 行导致了那个异常。因为您有一个 finally 子句,它会在您的生成器因异常而退出之前执行。

因此,在您的特定示例中,顺序如下:

  1. 使用 time_print("processes"):

    这将创建上下文管理器并对其调用 __enter__

  2. 生成器开始执行,t = time.time() 运行。

  3. yield 表达式暂停生成器,控制权返回装饰器。如果有 as target 部分,这将获取生成的任何内容并将其返回给 with 语句。这里生成了 None(只有一个普通的 yield 表达式)。

  4. [doproc() for _ in range(500)] 运行并完成。

  5. 运行上下文管理器__exit__方法,没有传入异常。

  6. 装饰器恢复生成器,它从中断处继续。

  7. 进入 finally: block 并执行 print task_name, "took", time.time() - t, "seconds."

  8. 生成器退出,装饰器__exit__方法退出,全部完成。

关于python - yield without value 在上下文管理器中做什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35489844/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com