Debabrata Bardhan
Debabrata Bardhan

Reputation: 47

Loop in python Generator

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)
        

Upvotes: 0

Views: 95

Answers (6)

Inadel
Inadel

Reputation: 101

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)

Upvotes: 0

Reda Belhaj
Reda Belhaj

Reputation: 1

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)

Upvotes: 0

Henry Tjhia
Henry Tjhia

Reputation: 752

Just replace FibNumber(num) with the following:

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

Upvotes: 0

Daweo
Daweo

Reputation: 36735

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)

Upvotes: 2

chepner
chepner

Reputation: 532268

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)

Upvotes: 2

napuzba
napuzba

Reputation: 6298

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

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

Upvotes: 0

Related Questions