循环嵌套生成器一次并重复

Cycle through nested generators once and repeat

我想通过 2 个不同的 itertools.count 屈服。我把两者结合起来 使用 itertools.chain.from_iterable

的生成器

这是我为它编写的代码。

return itertools.chain.from_iterable([itertools.count(start=2, step=2), itertools.count(start=7, step=7)])

问题是它试图在处理下一个计数器(第 7 步)之前完成第一个计数器(第 2 步)

上述示例代码的输出:

2
4
6
8
10
...

但是我想循环过来。

预期输出:

2  # 2*1
7  # 7*1
4  # 2*2
14 # 7*2
6  # 2*3
21 # 7*3
8  # 2*4
28 # 7*4

以下是我迄今为止尝试过的其他方法:

yield from [elem for elem in [next(count(start=2, step=2)), next(count(start=7, step=7))]]

以上交替循环,但计数器在每次屈服后重置。

上述代码示例的输出:

2
7
2
7
2
7

我希望这完全基于 itertools 或列表理解来实现 因为它们是内存优化的,所以我希望函数 return a generator object。另外,如果解决方案在一行上会更好。

编辑:

正如 jonrsharpe 在评论中所建议的那样,我已经实现了 roundrobin iter 技术并且我能够获取所需的输出。

from itertools import count, cycle

def pattern_generator():
    return cycle(iter(it).__next__ for it in [
        count(start=2, step=2),
        count(start=7, step=7),
    ])

gen = pattern_generator()

print(next(gen)())
print(next(gen)())
print(next(gen)())
print(next(gen)())

我对这个输出很满意。但是,是否可以在不调用 iter 的 next 方法的情况下调用 next?即,不在 next(gen)()?

中使用 ()

提前致谢。

您可以通过多种方式制作生成器

内联

#for i in (i for t in zip('abc',range(3)) for i in t):
#EDIT: more readable solution
for i in itertools.chain.from_iterable(zip('abc',range(3))):
    print(i)

编辑 2:解释
zip 连接每个可迭代的第 n 个(returns 序列 tuples ('a', 0), ('b', 1) ...
所以这大致转化为 itertools.chain.from_iterable([('a', 0), ('b', 1), ...])
调用 chain.from_iterable 类似于调用 chain
所以现在我们有 chain(('a', 0), ('b', 1), ('c', 2))
因为 tuple 是可迭代的,所以 chain 遍历 ('a', 0),然后 ('b', 1) 等等
from_iterablezip 都是必需的,因为两者都没有真正创建列表 [('a', 0), ('b', 1), ...] (在你的情况下,它是无限的)

函数 1

def alternate(*iterables):
    for t in zip(*iterables):
        yield from t # or for i in t: yield i

函数 2

def alternate(*iterables):
    iterables = [iter(it) for it in iterables]
    while True:
        try:
            for it in iterables:
                yield next(it)
        except StopIteration:
            break

结果

for i in alternate('abc', range(3)):
    print(i)
a
0
b
1
c
2

函数方法也提供了更大的灵活性