python中是否有一种方法可以更改处理get的收益的顺序? [英] Is there a way in python to change the order in which yield from get's processed?

查看:77
本文介绍了python中是否有一种方法可以更改处理get的收益的顺序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我这样做:

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

for num in foo():
    print(num)

我得到一个从0到19的有序列表. 在不更改范围函数输入的情况下,有一种简单的方法可以指定我想要的列表:0,10,1,11,2,12 ...

I get a ordered list from 0 to 19. Without change the input of the range functions, is there an easy way to specify that I want a list that goes: 0,10,1,11,2,12...

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

Basically I first want the first element of every generator. Than I want the second element of every generator and then the third and so on.

奖励积分: 有没有一种方法可以更改它,以便当生成器产生不相等的结果量时,第二个生成器在第一个生成器完成后产生其余的结果?

Bonus points: Is there a way to change it so that when the generators produce an unequal amount of results, the second generator yields the rest of it's results after the first one is finished?

推荐答案

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

You are trying to zip() your iterators; do so explicitly:

from itertools import chain

def foo():
    yield from chain.from_iterable(zip(range(10), range(10, 20)))

使用 itertools.chain.from_iterable() 在这里继续使用yield from,将zip()产生的元组展平.

The use of itertools.chain.from_iterable() lets you continue to use yield from here, flattening out the tuples zip() produces.

演示:

>>> 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() :

If you have generators of different lengths, you could use 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)

在这里,我在生成器表达式中使用了一个双循环的扁平化技术.

I used a different flattening technique here with a double loop in a generator expression.

这确实很乏味,并且由于您没有将yield from与另一个生成器一起使用(因此不需要传播对generator.send()generator.throw()的支持),您也可以将其设置为适当的循环:

This all does get tedious, and since you are not using yield from with another generator (so you don't need support for generator.send() and generator.throw() to be propagated), you may as well just make this a proper loop:

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            

您还可以使用 文档接收部分:

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))

这篇关于python中是否有一种方法可以更改处理get的收益的顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆