Python 生成器截止
我有一个生成器,它会不断生成一些数字,这些数字是根据特定的公式计算出来的。为了方便讨论,假设这个公式是这样的:
# this is not the actual generator, just an example
def Generate():
i = 0
while 1:
yield i
i+=1
接下来,我想从这个生成器中获取一些数字,这些数字要低于某个特定的阈值。我在想有没有一种更“pythonic”的方法来实现这个目标。我不想修改这个公式的定义。我知道可以用一个while循环来判断数字是否低于阈值,但我在想有没有更好的方法。我试过这样做,但很快就发现这样做不行。
l = [x for x in Generate() x<10000] # will go on infinitely
所以,有没有正确的方法来做到这一点呢?
谢谢
6 个回答
0
itertools.takewhile
这个函数会一直工作,直到遇到一个不符合条件的项为止。如果你想从一个可能顺序不固定的可迭代对象中返回所有值,我建议在 Python 2.x 中使用 itertools.ifilter
,就像下面这样:
from itertools import ifilter
f = ifilter(lambda x: x < 400, gen())
f.next()
这个方法成功地过滤了一个生成器,产生了介于 0 到 400 之间的随机整数,正如我们所希望的那样。
顺便提一下,itertools.ifilter
在 Python 3.x 中已经被弃用,取而代之的是内置的 filter()
,它在迭代时的语法稍有不同。
f = filter(lambda x: x < 400, gen())
next(f)
1
把你的生成器放在另一个生成器里面:
def no_more_than(limit):
def limiter(gen):
for item in gen:
if item > limit:
break
yield item
return limiter
def fib():
a,b = 1,1
while 1:
yield a
a,b = b,a+b
cutoff_at_100 = no_more_than(100)
print list(cutoff_at_100(fib()))
输出结果:
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
13
这是一个关于如何使用itertools
来创建另一个迭代器的解决方案:
from itertools import takewhile
l = takewhile(lambda x: x < 10000, generate())
如果你确定想要一个列表,可以把它放在list()
里面:
l = list(takewhile(lambda x: x < 10000, generate()))
或者,如果你想要一个列表,并且喜欢自己动手发明东西:
l = []
for x in generate():
if x < 10000:
l.append(x)
else:
break