首页 > 解决方案 > 输入 "with" 语句时 return 和 yield 的不同行为

问题描述

当我创建一个支持with作用域的类时,当我在方法中使用 yield 和 return 作为最后一次调用时,我会得到不同且无法解释的行为__enter__,代码:

class TestWith:
    def __init__(self, val):
        self.val=val

    def __enter__(self):
        print("Entered!")
        yield
        # return

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(f"In exit:, type: {exc_type}, val: {exc_val}, tb: {exc_tb}")


with TestWith(4):
    print("printme")

输出是:

printme
In exit:, type: None, val: None, tb: None

即“进入!” 不打印,更改__enter__方法为:

    def __enter__(self):
        print("Entered!")
        # yield
        return

结果是:

Entered!
printme
In exit:, type: None, val: None, tb: None

为什么这两个实现有不同的行为?我也想像“进入!” 无论如何都会被打印,因为它是在 return/yield 之前调用的

标签: python

解决方案


在函数定义中使用yield使函数成为生成器,并且工作方式完全不同。这是一个例子:

>>> def func1():
...   print('hi')
...   yield
...
>>> def func2():
...   print('hi')
...   return
...
>>> func1()  # returns a generator...doesn't execute the function!
<generator object func1 at 0x000002555B088510>
>>> func2()
hi
>>> g=func1()  # save the generator
>>> next(g)    # execute it to the next yield
hi
>>> next(g)    # No more yields throws an exception
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

__enter__意味着是一个正常的功能,而不是一个生成器,所以不要yield在这种情况下使用。


推荐阅读