Python создает генератор, который выводит несколько элементов - PullRequest
2 голосов
/ 22 апреля 2019

Есть ли способ в Python для генерации нескольких выходов одновременно. В частности, я хочу что-то вроде:

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

и скажите, что у меня есть параметр batch_size = 3. Я хотел бы, чтобы мой генератор вывел:

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

, где в последней команде он возвращает только два числа, потому что осталось только два числа, хотя batch_size равно 3.

Ответы [ 3 ]

5 голосов
/ 22 апреля 2019

На странице itertools предусмотрена функция группировщика:

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)

И с этим вы можете создать генератор и обернуть его группировщиком:

for my_tuple in grouper(my_gen, 3):
    print([x for x in my_tuple if x is not None])
2 голосов
/ 22 апреля 2019

ИМО, никаких библиотек не нужно.Вы можете просто определить свой собственный генератор пакетов

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

и просто

next(batch_iter(batch_size, x))

Итеративно-безопасная версия будет

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

Конечно, вы можете yield tuple(r) вместо r, если вам нужны значения кортежа.Вы также можете добавить предложение else и цикл break, поскольку, если val равно None, больше нет значений для итерации

1 голос
/ 22 апреля 2019

Вы можете использовать понимание списка с генератором:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...