【问题标题】:Loop over two generator together一起循环两个生成器
【发布时间】:2014-01-21 12:14:54
【问题描述】:

我有两个生成器,分别是 A()B()。我想一起迭代两个生成器。比如:

for a,b in A(),B():    # I know this is wrong
    #do processing on a and b

一种方法是将两个函数的结果存储在列表中,然后遍历合并的列表。像这样的:

resA = [a for a in A()]
resB = [b for b in B()]
for a,b in zip(resA, resB):
    #do stuff

如果您想知道,那么是的,这两个函数都产生相同数量的值。

但我不能使用这种方法,因为A()/B() 返回的值太多。将它们存储在列表中会耗尽内存,这就是我使用生成器的原因。

有没有办法同时遍历两个生成器?

【问题讨论】:

    标签: python loops for-loop generator yield


    【解决方案1】:

    几乎在那里。在 Python 3 中,只需将生成器传递给 zip()

    for a, b in zip(A(), B()):
    

    zip() 接受任何可迭代的,而不仅仅是列表。它会一个一个地消耗生成器。

    在 Python 2 中,使用 itertools.izip():

    from itertools import izip
    
    for a, b in izip(A(), B()):
    

    顺便说一句,将生成器变成列表就像list(generator) 一样简单;不需要在那里使用列表推导。

    【讨论】:

    • 纯学术上,如果A() 产生 1,2,3 和 B() 产生 4,5,6 这会产生 a,b = (1,4), (1,5), (1,6), (2,4), (2,5) ... (3,6) ?
    • @adsmith:没有。它产生(1, 4)(2, 5)(3, 6)。你在想itertools.product()
    【解决方案2】:

    听起来你想要itertools.izip

    from itertools import izip
    
    for a, b in izip(A(), B()):
    

    来自文档:

    类似于zip(),只是它返回的是迭代器而不是列表。

    因此,这样您就永远不会创建 listA()B()izip()

    请注意,Python 3 的基本 zip 类似于 Python 2.x 的 itertools.izip

    【讨论】:

    • 在这种情况下,两个列表必须具有相同数量的项目,如果第二个列表有更多项目,则不会打印
    • @san 具体来说,无论哪个参数较长,都将被截断为最短的长度。如果您需要处理对,这是必要的。如果您想获得尽可能多的项目,则可以使用[i]zip_longest,尽管如果您的论点之一是例如一个无限长的生成器你会遇到问题。
    【解决方案3】:

    您可以使用zip函数将生成的两个列表转换为元组列表,这样您就可以使用您想要的方式:

    for a,b in zip(A(), B()):
        pass
    

    【讨论】:

      猜你喜欢
      • 2019-07-07
      • 2023-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-03
      • 1970-01-01
      • 1970-01-01
      • 2019-03-08
      相关资源
      最近更新 更多