开发者

Infinite yield problem

Here is my simple code

class Fibonacci:
    @staticmethod
    def series():
        fprev = 1
        fnext = 1
        yield fnext
        while True:
            yield fnext
            fprev,fnext = fnext,fprev+fnext

under10 = (i for i in Fibonacci.series() if i<10)
for i in under10 :
    print i

It's absolutely obvious, but...WHY interpreter is executing block

while True:
                yield fnext
                fprev,fnext = fnext,fprev+fnext

Forever? I specified in generator,that I want only elements<10

under10 = (i for i in Fibonacci.series() if i<10)

IMHO, it's a little bit misunderstanding Any way to prevent infinite execution without re-writing "series"?开发者_如何学Python


How should the interpreter know that all future numbers will be < 10? It would have to either know (somehow) that it’s churning out the Fibonacci series, or it would have to inspect the whole series.

It can’t do the first, so it does the second.

You can fix this by using itertools.takewhile:

import itertools

under10 = itertools.takewhile(lambda n: n < 10, Fibonacci.series())


under10 = (i for i in Fibonacci.series() if i<10) 

Will keep going, it just won't yield values greater than 10. There's nothing instructing the for loop to stop.

You would probably have better luck doing something like:

for i in Fibonacci.series():
    if i > 10:
        break
    #do your appends and such here

EDIT:

I like Konrad's itertools example much more, I always forget about itertools


The infinite loop isn't a result of the while True: in the Fibonacci.series() method. It's caused by the under10 = (i for i in Fibonacci.series() if i<10) generator which just keeps going since it doesn't realize the values yielded will never get smaller. Here's [another] way to fix it and generalize it at the same time -- without re-writing series() -- using the itertools.takewhile() iterator:

import itertools
fibos_under = lambda N: itertools.takewhile(lambda f: f < N, Fibonacci.series())

for i in fibos_under(10):
    print i

BTW: You can simplify the Fibonacci.series() method slightly by changing it to this which yields the same values:

class Fibonacci:
    @staticmethod
    def series():
        fprev,fnext = 0,1
        while True:
            yield fnext
            fprev,fnext = fnext,fprev+fnext
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜