RPiAwesomeness
RPiAwesomeness

Reputation: 5159

LearnPython.org Generators trouble

I'm learning python via learnpython.org. I made it through all of the basic classes just fine, but I'm having trouble with the Generators level.

I think I understand how the yield command works, but I can't figure out how to use it to get the Fibonacci sequence I need to complete the lesson. Here's my code, but it only gives me the first 2 numbers.

# fill in this function
def fib():
    a,b = 1,0  # Sets the values (is this causing a problem?)
    yield a    # Sends back the value of a to the iterator (for loop)
    b = a + b  # Sets the value of b to a + b
    yield b    # Sends back the value of b to the iterator (for loop)

# testing code
import types
if type(fib()) == types.GeneratorType:
    print "Good, The fib function is a generator."

    counter = 0
    for n in fib():
        print n
        counter += 1
        if counter == 10:
            break

This is most annoying, as I would like to complete this level, but I don't know how.

Upvotes: 1

Views: 106

Answers (2)

Robᵩ
Robᵩ

Reputation: 168626

Your generator will produce one result for each yield statement executed. You only executed two yield statements, so your generator produced two results.

Try this:

def fib():
    a,b = 1,0  # Sets the values (is this causing a problem?)
    while True:
        a,b = b, a + b  # Sets the value of b to a + b
        yield b    # Sends back the value of b to the iterator (for loop)

As you can see, the while loop will run forever, so this generator will produce an indefinite (infinite?) number of results.


Alternatively, you can modify your generator to produce a finite sequence, and modify your caller to take advantage of that:

def fib(counter=None, limit=None):
    a,b = 0,1
    i = 0
    while (counter is None or counter > i) and (limit is None or limit > b):
        i += 1
        yield b
        a,b = b, a + b

print list(fib(counter=10))
print list(fib(limit=60))

Upvotes: 4

kazagistar
kazagistar

Reputation: 1597

In python, there is always an implicit return at the end of each function. So when your generator reaches the end of the function, after the second yield, it halts. If you want to keep going (an infinite generator) you need to put the yields in an infinite loop.

def fib():
    current, past = 1, 0
    while True:
        yield current
        current, past = current + past, current

Side note:

Also, python has a nice function for grabbing the first N items from an infinite generator built in to a cool library called itertools, so the second part could be cleaned up like this:

from itertools import islice
for number in islice(fib(), 10):
    print(number)

Upvotes: 0

Related Questions