Python Generator Cutoff

时间:2013-02-01 19:46:48

标签: python python-2.7 generator

我有一个发电机,它将继续提供符合特定公式的数字。为了论证,我们假设这是函数:

# 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 :(得分:11)

创建另一个迭代器的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

答案 1 :(得分:0)

只需使用计数器作为无限生成器:

gen=Generate()        # your generator function example
l=[gen.next() for i in range(100)]

但是因为它是一个生成器,所以使用生成器表达式:

seq=(gen.next() for i in xrange(100))  #need x in xrange in Python 2.x; 3.x use range

修改

好的,然后只需使用控制器:

def controler(gen,limit):
    n=gen.next()
    while n<limit:
        yield n
        n=gen.next()

seq=[i for i in controler(Generate(),100)]

答案 2 :(得分:0)

将发电机包裹在另一台发电机内:

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]

答案 3 :(得分:0)

Generate()替换为xrange(10000)

答案 4 :(得分:0)

itertools.takewhile只有在遇到不符合谓词的项目时才会起作用。如果你需要从一个可能无序的可迭代中返回所有值,我建议使用itertools.ifilter用于Python 2.x,如

from itertools import ifilter
f = ifilter(lambda x: x < 400, gen())
f.next()

这过滤了一个生成器,产生0到400之间的随机整数。

FWIW itertools.ifilter在Python 3.x中不赞成使用内置filter(),其迭代语法略有不同

f = filter(lambda x: x < 400, gen())
next(f)

答案 5 :(得分:0)

将其包装在一定范围的zip生成器中:

gen = range(100_000_000_000)
limit = 10
(z[1] for z in zip(range(limit), gen))

zip创建一个元组,这就是z[1]

的原因

这可以在for循环中使用:

for g in (z[1] for z in zip(range(limit), gen)):
    print(g)

或者您可以使用lambda

wrap = lambda gen, limit: (z[1] for z in zip(range(limit), gen))
for g in wrap(gen, 10):
    print(g)