I have a generator with the return value
statement in it.
If i use next on it I get the Stopiteration: value
from it as expected.
However when I use yield from
the value
is lost.
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:
Is there a way to preserve the value
when using yield from
?
Is this working as intended or maybe it is a bug ?
By receiving the value sent by the sub-generator in the yield from
statement.
Taking a quote from PEP 380 -- Syntax for Delegating to a Subgenerator:
The value of the
yield from
expression is the first argument to theStopIteration
exception raised by the iterator when it terminates.
So with a small tweak, res
in the new
generator will contain the value of StopIteration
raised from the test
subgenerator:
def new():
res = yield from test()
return res
Now when next(n)
is executed you'll get the value in the Exception message:
n = new()
next(n)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-39-1c47c7af397e> in <module>()
----> 1 next(n)
StopIteration: 1
Oh, and as an addendum, you can of course get the 'return' value without it being encapsulated in the StopIteration
object by using yield
again:
def new():
res = yield from test()
yield res
Now calling next(new())
will return the value returned from test()
:
next(new())
Out[20]: 1