您正在尝试 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
您还可以使用itertools documentation recipies section 中列出的roundrobin() 配方:
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))