2016-01-30 5 views
2

У меня есть генератор с оператором return value. Если я использую следующий на нем, я получаю Stopiteration: value от него, как и ожидалось. Однако, когда я использую yield from, теряется value.выход от генератора с возвратом <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: 

Есть ли способ сохранить value при использовании yield from? Работает ли это так, как предполагалось, или, может быть, это ошибка?

ответ

2

Получив значение, отправленное подгенератором в инструкции yield from.

Принимая цитату из PEP 380 -- Syntax for Delegating to a Subgenerator:

Значения выражения yield from является первым аргументом в StopIteration исключение, поднятого итератором, когда она заканчивается.

Так с небольшой подстройкой, res в new генераторе будет содержать значение StopIteration поднятого из test subgenerator:

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

Теперь, когда next(n) выполняется вы получите значение в Exception сообщение:

n = new() 

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

StopIteration: 1 

О, и в качестве дополнения, вы можете, конечно, получить значение «возвращение» без него инкапсулируется в StopIteration объекта с помощью yield снова:

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

Теперь вызова next(new()) возвратит значение, возвращаемое из test():

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