Что делает return при использовании выражения yield from?
Я не смог найти никаких примеров возвращаемых значений из yield from
выражение Я пробовал этот простой код, но безуспешно:
def return4():
return 4
def yield_from():
res = yield from range(4)
res = yield from return4()
def test_yield_from():
for x in yield_from():
print(x)
test_yield_from()
Который производит:
» python test.py
0
1
2
3
Traceback (most recent call last):
File "test.py", line 52, in <module>
test_yield_from()
File "test.py", line 48, in test_yield_from
for x in yield_from():
File "test.py", line 44, in yield_from
res = yield from return4()
TypeError: 'int' object is not iterable
Но я ожидал:
» python test.py
0
1
2
3
4
Потому что, как указано в PEP:
Кроме того, когда итератор является другим генератором, субгенератору разрешается выполнять оператор возврата со значением, и это значение становится значением выхода из выражения.
Очевидно, я не получаю это объяснение. Как это return
в работе "субгенератора" в отношении yield from
?
3 ответа
Генераторы могут возвращать значение, когда они исчерпаны:
def my_gen():
yield 0
return "done"
g = my_gen()
next(g)
next(g) # raises StopIteration: "done"
Возвращаемое значение в yield from
Заявление будет этим значением. например.
def yield_from():
res = yield from my_gen()
assert res == "done"
По умолчанию это значение None
, То есть res = yield from range(4)
установит res
как None
,
yield from generator
коротка для
for i in generator:
yield i
ну, это немного сложнее, чем это: https://www.python.org/dev/peps/pep-0380/.
это не будет работать хорошо, если generator = 4
, (ваш return4()
не генератор. это функция.)
чтобы получить то, что вы хотите, вы просто сделаете это:
def yield_from():
yield from range(4)
yield 4
Я публикую рабочий пример для ваших тестов.
Функция return4 теперь является генератором. Для этого в любом месте функции должен присутствовать выход (в Python 3.5 есть новая связанная функция, но сейчас это не важно).
Как вы уже цитировали:
Кроме того, когда итератор является другим генератором, субгенератору разрешается выполнять оператор return со значением, и это значение становится значением выхода из выражения
Резюме: вы получите значение. Вы можете напечатать это, например:
def yield_from():
# ...
val = yield from return4()
print("value:", val) # prints value: 4
Но вы хотите уступить, а не печатать. Вот полный код:
def return4():
if False:
yield None
return 4
def yield_from():
yield from range(4)
yield (yield from return4())
def test_yield_from():
for x in yield_from():
print(x)
test_yield_from()
# prints numbers 0 to 4
Вы, наверное, спрашиваете себя, для чего это хорошо. Нет почти никакого преимущества, когда вы получаете только значения от генератора. Но yield from
это отличная функция, когда вы отправляете значения в генератор. Попробуйте найти хорошее объяснение сопрограмм Python. Это удивительно