0

I was trying python's generators (together with from) but endup with infinite loop. My python version is python3. why did I stuck into infinite loop?

Below is my code:

def fib2():
    a,b = 0,1
    while True:    
        yield a
        a,b = b , a+b


def FibNumber(num):
    fi2= fib2()
    for i in range(num):
        yield from fi2


if (__name__ == "__main__"):
 
    fin = FibNumber(10)
    for i in fin:
        print (i)
        

6 Answers 6

2

fin is indeed an infinite generator. FiBNumber doesn't do what you intended; for each value of i, it tries to yield everything from fi2. A more correct definition would be

def FibNumber(num):
    fi2 = fib2()
    for i in range(num):
        yield next(fi2)

However, you are really just reimplementing itertools.islice:

from itertools import islice


for i in islice(fib2(), 10):
    print(i)
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your reply. I have one more doubt is that when I ran this same code on pdb debugger then I noticed it was iterating over i in FibNumber method and printing Fibonacci numbers one after another. So you mean when I generated fi2 then python3 produced as much as possible big iterable and returned the iterator?
2

This is due to fact that you used yield from with infinite generator. PEP 380 says that:

yield from <expr>

where <expr> is an expression evaluating to an iterable, from which an iterator is extracted. The iterator is run to exhaustion, during which time it yields and receives values directly to or from the caller of the generator containing the yield from expression (the "delegating generator").

(bold by me)

1 Comment

Add a working example for the answer to be complete
0

You can use the __next__() in the second iterator.

def FibNumber(num):
    fi2= fib2()
    for i in range(num):
        yield fi2.__next__()

Comments

0

Just replace FibNumber(num) with the following:

def FibNumber(num):
    fi2= fib2()
    yield from (next(fi2) for i in range(num))

Comments

0

I think you have to force a break in your for loop.

def fib2():
a,b = 0,1
while True:    
    yield a
    a,b = b , a+b

def FibNumber(num):
    fi2= fib2()
    a = 0
    for i in fi2:
       a += 1
       if a > num:
          break
       yield i

if (__name__ == "__main__"):

    fin = FibNumber(10)
    for i in fin:
        print (i)

Comments

0

Use the next value of your fib2 generator for every sequence of loops.

def fib2(n):
    a,b = 0,1
    i = 0
    while i <=n:    
        yield a
        a,b = b , a+b


def FibNumber(num):
    fi2= fib2()
    for i in range(num):
        yield next(fi2)


if (__name__ == "__main__"):
 
    fin = FibNumber(10)
    for i in fin:
        print (i)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.