带if条件的生成器的python列表理解

带if条件的生成器的python列表理解,python,python-2.7,Python,Python 2.7,我试图在生成器上使用if条件执行列表理解,但代码卡在for循环中 import time def gen(): a = 0 b = 1 while True: a += 1 b += 1 yield a, b init_time = time.time() m = [{'a': x, 'b': y} for x, y in gen() if time.time() - init_time < 3]

我试图在生成器上使用if条件执行列表理解,但代码卡在for循环中

import time
def gen():
    a = 0
    b = 1
    while True:
        a += 1
        b += 1
        yield a, b
    init_time = time.time() 
    m = [{'a': x, 'b': y} for x, y in gen() if time.time() - init_time < 3]
我意识到这是因为gen将无限返回,而for将继续执行,直到gen可执行为止。还有其他方法吗?

如果列表理解中的条件不是停止条件,它是一个过滤器。如前所述,3秒钟后,它将开始忽略来自生成器的对,并且永远不会返回到目前为止所创建的列表

另一个问题是列表理解目前在生成器中,这在非常特殊的情况下不是如何使用列表理解生成器。列表理解在生成器生成的对象上进行迭代,与生成器的定义无关

最后,您的生成器是无限的。虽然无限生成器是完全有效且非常有用的,但它们不能传递给列表理解,因为列表理解需要消耗整个生成器,而根据定义,无限生成器是不可能的。然而,我们可以编写一个有限生成器来适应无限生成器,当达到某个条件时停止。是标准库中此类包装器的一个示例,但您可以轻松编写自己的包装器。基于时间的包装可能如下所示:

def iter_until(tm, iterable):
    t0 = time.time()
    for val in iterable:
        yield val
        if time.time() - t0 > tm:
            break
此包装器可以轻松地与原始的无限生成器组合,并用于列表比较:

def gen():
    a = 0
    b = 1
    while True:
        a += 1
        b += 1
        yield a, b

m = [{'a': x, 'b': y} for x, y in iter_until(3, gen())]

你认为它会怎样结束?终端条件是什么?您的代码格式是否正确?如果你把最后两行独立出来,它就可以工作了。我希望在3秒内为生成器生成的所有值创建一个dict列表seconds@DYZ它无法工作,因为生成器仍然是无限的。它只会停止向列表中添加值,但永远不会返回到目前为止创建的列表。@AamirShaikh然后您应该在生成器中移动计时器,并使用它终止loopg=gen;而time.time-time<3:g.next;g、 关闭这是当前的方法,我想优化it@AamirShaikh答案提供了用惯用Python实现的代码——请参见iter_中的for循环。