72

在 Python 2 中,函数定义中 return 与 yield 一起出现错误。但是对于 Python 3.3 中的这段代码

def f():
  return 3
  yield 2

x = f()
print(x.__next__())

在有收益的函数中使用 return 没有错误。但是,当__next__调用该函数时,会抛出异常 StopIteration。为什么不只是返回值3?这个回报是否被忽略了?

4

2 回答 2

82

这是 Python 3.3 中的一个新功能(正如注释所述,它甚至在 3.2 中都不起作用)。很像returnin a generator 早就等价于raise StopIteration()return <something>in a generator 现在等价于raise StopIteration(<something>)。因此,您看到的异常应该打印为StopIteration: 3,并且可以通过value异常对象上的属性访问该值。如果生成器被委托使用(也是新的)yield from语法,它就是结果。有关详细信息,请参阅PEP 380

def f():
    return 1
    yield 2

def g():
    x = yield from f()
    print(x)

# g is still a generator so we need to iterate to run it:
for _ in g():
    pass

这打印1,但不是2

于 2013-05-27T20:25:26.163 回答
42

返回值不会被忽略,但生成器只产生值,areturn只是结束生成器,在这种情况下提前。在这种情况下,推进生成器永远不会到达yield语句。

每当迭代器到达要产生的值的“结束”时,StopIteration 必须引发 a。发电机也不例外。然而,从 Python 3.3 开始,任何return表达式都会成为异常的值:

>>> def gen():
...     return 3
...     yield 2
... 
>>> try:
...     next(gen())
... except StopIteration as ex:
...     e = ex
... 
>>> e
StopIteration(3,)
>>> e.value
3

使用该next()函数来推进迭代器,而不是.__next__()直接调用:

print(next(x))
于 2013-05-27T20:18:10.697 回答