Python 进入时回报和收益的不同行为;加上;陈述

Python 进入时回报和收益的不同行为;加上;陈述,python,Python,当我创建一个支持范围为的类时,当我在\uuuuuu enter\uuuuu方法中使用yield和return作为最后调用时,我会得到不同的、无法解释的行为,代码: class TestWith: def __init__(self, val): self.val=val def __enter__(self): print("Entered!") yield # return def

当我创建一个支持范围为的
类时,当我在
\uuuuuu enter\uuuuu
方法中使用yield和return作为最后调用时,我会得到不同的、无法解释的行为,代码:

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
i、 e.“已输入!”未打印,将
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

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

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

为什么这两种实现有不同的行为?此外,我还可以想象,“Entered!”无论如何都会被打印出来,因为它是在return/yield

之前调用的。您可能会混淆用于创建上下文管理器的“yield语法”(addind
,支持函数而不需要创建类)

从contextlib导入contextmanager
@上下文管理器
def TestWith(val):
打印(“已输入!”)
产量
打印(“退出”)
使用TestWith(4):
打印(“打印我”)
输出:

Entered!
printme
Exit

在函数定义中使用
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
>>def func1():
...   打印('hi')
...   产量
...
>>>def func2():
...   打印('hi')
...   返回
...
>>>func1()#返回一个生成器…不执行该函数!
>>>func2()
你好
>>>g=func1()#保存生成器
>>>next(g)#执行到下一个收益率
你好
>>>下一步(g)#没有更多收益抛出异常
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
停止迭代

\uuuu enter\uuuu
是一个普通函数,而不是生成器,所以在这种情况下不要使用
yield

好吧,
yield
return
做不同的事情,那么为什么你认为它们都应该在这里工作呢?@KonradRudolph他们是。它们如何影响在实际调用之前发生的函数调用?因为
return
yield
不是函数调用。它们是控制流语句,这意味着它们控制整个函数的行为。在
yield
的特定情况下,它的使用导致函数具有完全不同的语义,包括不同的返回值和不同的语句序列。这与上下文管理器无关,这只会使示例变得复杂。问题基本上是“什么是生成器函数”。事实上,上下文管理器的使用让我想到了这个奇怪的场景,但它并没有真正回答这个问题。谢谢你的例子