[英]python list comprehension on generator with if condition
我试图用生成器上的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()
将无限返回,并且将继续执行直到gen()
可迭代,还有其他方法吗?
列表推导中的if
条件不是停止条件,而是一个filter 。 如所写,3秒钟后,它将仅开始忽略来自生成器的配对,并且永远不会返回到目前为止的列表。
另一个问题是列表推导当前位于生成器内部,这(在非常特殊的情况下除外)不是生成器使用列表推导的方式。 列表理解对生成器生成的对象进行迭代,而与生成器的定义无关。
最后,您的生成器是infinite 。 尽管无限生成器是完全有效且非常有用的,但它们无法传递给列表推导,因为列表推导要消耗整个生成器,按照定义,无限生成器是不可能的。 但是,可以编写适应无限生成器的有限生成器,并在达到条件时停止。 itertools.islice
是标准库中此类包装器的示例,但是您可以轻松编写自己的包装器。 基于时间的包装器可能如下所示:
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())]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.