从其中包含 return <value> 语句的生成器中产生

yield from a generator that has return <value> statement in it

我有一个带有 return value 语句的生成器。 如果我在它上面使用 next,我会按预期从中得到 Stopiteration: value 。 但是,当我使用 yield from 时,value 丢失了。

In [1]: def test():
   ...:     return 1
   ...:     yield 2
   ...:

In [2]: t = test()

In [3]: t
Out[3]: <generator object test at 0x000000000468F780>

In [4]: next(t)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-4-9494367a8bed> in <module>()
----> 1 next(t)

StopIteration: 1

In [5]: def new():
   ...:     yield from test()
   ...:

In [6]: n = new()

In [7]: n
Out[7]: <generator object new at 0x00000000050F23B8>

In [8]: next(n)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-8-1c47c7af397e> in <module>()
----> 1 next(n)

StopIteration:

有没有办法在使用 yield from 时保留 value ? 这是按预期工作还是可能是错误?

通过接收子生成器在yield from语句中发送的值。

引自PEP 380 -- Syntax for Delegating to a Subgenerator:

The value of the yield from expression is the first argument to the StopIteration exception raised by the iterator when it terminates.

因此,通过一个小的调整,new 生成器中的 res 将包含从 test 子生成器中产生的 StopIteration 的值:

def new():
   res = yield from test()
   return res

现在,当执行 next(n) 时,您将在异常消息中获得值:

n = new()

next(n)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-39-1c47c7af397e> in <module>()
----> 1 next(n)

StopIteration: 1

哦,作为补充,你当然可以通过再次使用yield获得'return'值而不用将其封装在StopIteration对象中:

def new():
    res = yield from test()
    yield res

现在调用 next(new()) 将 return 来自 test() 的值 return:

next(new())
Out[20]: 1