Вы пытаетесь использовать итераторы zip()
; сделать это явно:
from itertools import chain
def foo():
yield from chain.from_iterable(zip(range(10), range(10, 20)))
Использование itertools.chain.from_iterable()
позволяет продолжать использовать yield from
здесь, уплощение кортежи zip()
производит.
Демо:
>>> from itertools import chain
>>> def foo():
... yield from chain.from_iterable(zip(range(10), range(10, 20)))
...
>>> list(foo())
[0, 10, 1, 11, 2, 12, 3, 13, 4, 14, 5, 15, 6, 16, 7, 17, 8, 18, 9, 19]
Если у вас есть генераторы различной длины, можно использовать itertools.zip_longest()
:
from itertools import zip_longest
def foo():
yield from (i for pair in zip_longest(range(10), range(10, 22))
for i in pair if i is not None)
Я использовал другую технику, уплощение здесь с двойной петлей в выражении генератора.
Это все действительно становится утомительным, и так как вы не используете yield from
с другим генератором (так что вам не нужна поддержка generator.send()
и generator.throw()
быть распространяемый), вы можете также просто сделать это правильный цикл:
def foo():
for x, y in zip_longest(range(10), range(10, 22)):
if x is not None:
yield x
if y is not None:
yield y
Вы можете также использовать roundrobin()
рецепт, указанный в itertools
documentation recipies section:
from itertools import cycle
def roundrobin(*iterables):
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
# Recipe credited to George Sakkis
pending = len(iterables)
nexts = cycle(iter(it).__next__ for it in iterables)
while pending:
try:
for next in nexts:
yield next()
except StopIteration:
pending -= 1
nexts = cycle(islice(nexts, pending))
def foo():
yield from roundrobin(range(10), range(10, 22))
Что делать, если генераторы имеют различную длину? Это решение, похоже, молча забывает остальную цепь. Я бы предпочел, чтобы все остальное. – Christian
@Christian: используйте ['itertools.zip_longest'] (https://docs.python.org/3/library/itertools.html#itertools.zip_longest), возможно, отфильтровывая значения' None'. Но вам придется делать это * явно *. –
@MartijnPieters Я думаю, что я сказал это раньше¹, но ... «roundrobin» из документов, может быть? ¹http: //stackoverflow.com/a/23874310/1763356 – Veedrac