3

我有一个生成器,它会不断给出遵循特定公式的数字。为了论证,假设这是函数:

# 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

那么有没有正确的方法来做到这一点。

谢谢

4

6 回答 6

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
于 2013-02-01T19:49:08.703 回答
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]
于 2013-02-01T21:04:48.533 回答
0

itertools.takewhile只会在遇到不满足谓词的项目之前起作用。如果您需要从可能无序的迭代中返回所有值,我建议使用itertools.ifilterPython 2.x,如

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

这过滤了生成器,如希望的那样产生 0 到 400 之间的随机整数。

FWIWitertools.ifilter在 Python 3.x 中被弃用,取而代之的是内置的,filter()它的迭代语法略有不同

f = filter(lambda x: x < 400, gen())
next(f)
于 2013-02-02T00:00:54.663 回答
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)
于 2020-09-11T14:31:15.617 回答
-1

只需将计数器用于无限生成器:

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)]
于 2013-02-01T19:55:08.567 回答
-1

替换Generate()xrange(10000)

于 2013-02-01T23:51:45.513 回答