您正在嘗試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))
如果什麼發生器有不同的長度?這個解決方案似乎默默忘記了鏈條的其餘部分。我寧願我仍然休息。 – Christian 2014-09-13 14:15:59
@Christian:然後使用['itertools.zip_longest'](https://docs.python.org/3/library/itertools.html#itertools.zip_longest),可能會過濾出'None'值。但是你必須明確地*這樣做*。 – 2014-09-13 14:17:19
@MartijnPieters我想我以前曾經說過這個,但是......從文檔中找到'roundrobin',也許呢? ¹http://stackoverflow.com/a/23874310/1763356 – Veedrac 2014-09-13 18:52:51