有没有办法在python中改变get处理的收益顺序?

Chr*_*ian 2 python yield generator python-3.x

如果我做:

def foo():
    yield from range(0,10)
    yield from range(10,20)

for num in foo():
    print(num)
Run Code Online (Sandbox Code Playgroud)

我得到一个从0到19的有序列表.如果没有更改范围函数的输入,是否有一种简单的方法来指定我想要一个列表:0,10,1,11,2,12 ......

基本上我首先想要每个发生器的第一个元素.比我想要每个发生器的第二个元素然后第三个,依此类推.

奖励点:有没有办法改变它,以便当发电机产生不等量的结果时,第二个发电机在第一个发电机完成后产生剩余的结果?

Mar*_*ers 7

你正在尝试zip()你的迭代器; 明确地这样做:

from itertools import chain

def foo():
    yield from chain.from_iterable(zip(range(10), range(10, 20)))
Run Code Online (Sandbox Code Playgroud)

使用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]
Run Code Online (Sandbox Code Playgroud)

如果你有不同长度的发电机,你可以使用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)
Run Code Online (Sandbox Code Playgroud)

我在这里使用了不同的展平技术,在生成器表达式中使用了双循环.

这一切都变得乏味,并且因为你没有使用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            
Run Code Online (Sandbox Code Playgroud)

您还可以使用文档收件人部分中roundrobin()列出的配方:itertools

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))
Run Code Online (Sandbox Code Playgroud)