一旦发电机列表中的发电机用尽,是否继续使用其他发电机?
Continue to other generators once a generator has been exhausted in a list of generators?
我在函数 alternate_all(*args)
中有一个生成器列表,它在列表中的每个生成器之间交替打印它们的第一个项目、第二个项目……等等,直到所有生成器都用完。
我的代码一直工作到生成器耗尽,一旦 StopIteration 发生,它就会停止打印,当我希望它继续使用其余生成器并忽略耗尽的生成器时:
def alternate_all(*args):
iter_list = []
for iterable in args:
iter_list.append(iter(iterable))
try:
while True:
for iterable in iter_list:
val = next(iter_list[0])
iter_list.append(iter_list.pop(0))
yield val
except StopIteration:
pass
if __name__ == '__main__':
for i in alternate_all('abcde','fg','hijk'):
print(i,end='')
我的输出是:
afhbgic
什么时候应该是:
afhbgicjdke
我怎样才能让它忽略耗尽的发电机?我宁愿不使用 itertools 并保持相同的结构。
看到Kaya的回答,好多了。
直接来自 itertools
文档的 itertools-recipe roundrobin
怎么样?不过,您最终仍会使用 itertools.cycle
和 itertools.islice
,但不确定这是否会破坏交易。
def roundrobin(*iterables):
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
# Recipe credited to George Sakkis
num_active = len(iterables)
nexts = cycle(iter(it).__next__ for it in iterables)
while num_active:
try:
for next in nexts:
yield next()
except StopIteration:
# Remove the iterator we just exhausted from the cycle.
num_active -= 1
nexts = cycle(islice(nexts, num_active))
这行得通。我试图接近您的原始代码的工作方式(尽管为了简单起见,我确实用列表理解替换了您的第一个循环)。
def alternate_all(*args):
iter_list = [iter(arg) for arg in args]
while iter_list:
i = iter_list.pop(0)
try:
val = next(i)
except StopIteration:
pass
else:
yield val
iter_list.append(i)
您的代码的主要问题是您的 try
/except
在循环之外,这意味着第一个耗尽的迭代器将从循环中退出。相反,您想在循环中捕获 StopIteration
以便您可以继续进行,并且循环应该继续进行,而 iter_list
仍然有任何迭代器。
我在函数 alternate_all(*args)
中有一个生成器列表,它在列表中的每个生成器之间交替打印它们的第一个项目、第二个项目……等等,直到所有生成器都用完。
我的代码一直工作到生成器耗尽,一旦 StopIteration 发生,它就会停止打印,当我希望它继续使用其余生成器并忽略耗尽的生成器时:
def alternate_all(*args):
iter_list = []
for iterable in args:
iter_list.append(iter(iterable))
try:
while True:
for iterable in iter_list:
val = next(iter_list[0])
iter_list.append(iter_list.pop(0))
yield val
except StopIteration:
pass
if __name__ == '__main__':
for i in alternate_all('abcde','fg','hijk'):
print(i,end='')
我的输出是:
afhbgic
什么时候应该是:
afhbgicjdke
我怎样才能让它忽略耗尽的发电机?我宁愿不使用 itertools 并保持相同的结构。
看到Kaya的回答,好多了。
直接来自 itertools
文档的 itertools-recipe roundrobin
怎么样?不过,您最终仍会使用 itertools.cycle
和 itertools.islice
,但不确定这是否会破坏交易。
def roundrobin(*iterables):
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
# Recipe credited to George Sakkis
num_active = len(iterables)
nexts = cycle(iter(it).__next__ for it in iterables)
while num_active:
try:
for next in nexts:
yield next()
except StopIteration:
# Remove the iterator we just exhausted from the cycle.
num_active -= 1
nexts = cycle(islice(nexts, num_active))
这行得通。我试图接近您的原始代码的工作方式(尽管为了简单起见,我确实用列表理解替换了您的第一个循环)。
def alternate_all(*args):
iter_list = [iter(arg) for arg in args]
while iter_list:
i = iter_list.pop(0)
try:
val = next(i)
except StopIteration:
pass
else:
yield val
iter_list.append(i)
您的代码的主要问题是您的 try
/except
在循环之外,这意味着第一个耗尽的迭代器将从循环中退出。相反,您想在循环中捕获 StopIteration
以便您可以继续进行,并且循环应该继续进行,而 iter_list
仍然有任何迭代器。