简体   繁体   English

Python创建一个输出多个项目的生成器

[英]Python creating a generator that outputs multiple items

Is there a way in Python to generate multiple outputs at the same time. Python 中有没有一种方法可以同时生成多个输出。 In particular I want something like:特别是我想要这样的东西:

my_gen =(i for i in range(10))

and say I have a parameter batch_size = 3 .并说我有一个参数batch_size = 3 I would want my generator to output:我希望我的生成器输出:

my_gen.next()
0,1,2
my_gen.next()
3,4,5
my_gen.next()
6,7,8
my_gen.next()
9,10

where on the last command, it only yields two numbers because there are only two numbers left even though the batch_size is 3.在最后一个命令中,它只产生两个数字,因为即使batch_size为 3,也只剩下两个数字。

On the itertools page there is a grouper function provided:itertools页面上提供了一个 grouper 函数:

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)

And with that you can make your generator and wrap it with a grouper:然后你可以制作你的发电机并用石斑鱼包裹它:

for my_tuple in grouper(my_gen, 3):
    print([x for x in my_tuple if x is not None])

IMO, no need for any libraries. IMO,不需要任何图书馆。 You may just define your own batch generator您可以只定义自己的批处理生成器

def batch_iter(batch_size, iter_):
    yield [next(iter_) for _ in range(batch_size)]

and just只是

next(batch_iter(batch_size, x))

A iteration-safe version would be迭代安全版本将是

def batch_iter(batch_size, iter_):
    r = []
    for _ in range(b):
        val = next(iter_, None)
        if val is not None: r.append(val)
    yield r

Of course you may yield tuple(r) instead of just r if you need tuple values.当然,如果您需要元组值,您可以生成yield tuple(r)而不仅仅是r You may also add an else clause and break the loop since once val is None , there are no more values to iterate您还可以添加一个else子句并break循环,因为一旦valNone ,就没有更多的值可以迭代

You can use list comprehension with the generator:您可以将列表理解与生成器一起使用:

batch_size, max_size = 3, 10
my_gen = ([x for x in range(i, i + batch_size) if x <= max_size] for i in range(0, max_size, batch_size))
for x in my_gen:
    print(x)

If you expect the iterator/generator to have a multiple of the batch size elements you can simply do:如果您希望迭代器/生成器具有批处理大小元素的倍数,您可以简单地执行以下操作:

gen = iter(range(12))
for x, y, z in iter(lambda: [next(gen) for _ in range(3)], 1):
    print(x, y, z)

If not;如果不; this should suit your needs:这应该适合您的需要:

gen = iter(range(11))
for t in iter(lambda: [next(gen, None) for _ in range(3)], [None]*3):
    print(*[x for x in t if x is not None])

Pros:优点:

  1. iteration safe迭代安全
  2. readable可读的
  3. requires no library不需要图书馆
  4. short短的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM