Python: Fibonacci Sequence

Da Bx picture Da Bx · Mar 9, 2013 · Viewed 13.7k times · Source

I'm just trying to improve my programming skill by making some basic functions.

I want to fill a list with fibonacci values, but I think my code gives the sum of all the numbers put together and prints that instead..

numberlist = []
i = 0
for i in range(20):
    numberlist.append(i)

print numberlist

fibonaccinumbers = []

for n in numberlist:
    def fib(n):
        a, b = 0, 1
        for i in range(n):
            a, b = b, a + b
        return a
    a = fib(n)
    fibonaccinumbers.append(a)


print a

Where have I gone wrong?

Answer

poke picture poke · Mar 9, 2013
print a

Well, you print the final value.


Also some more comments on your code:

numberlist = []
i = 0
for i in range(20):
    numberlist.append(i)

You don’t need to initialize i there, the for loop does that for you. Also, you can simplify the whole block by just doing this:

numberlist = list(range(20))

And given that you don’t actually need that to be a list, you don’t need to construct that at all but you can just run for n in range(20) later.

Then you are redefinining your fib function inside the loop over and over again. You should define it outside of it and just reuse it.

Also, when you know you want to create a list of multiple fibonacci numbers, it helps to just store all the numbers you calculate in between. That way you don’t have to do the same things over and over again. You can also use a generator function to make that all easier:

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

fibonaccinumbers = []
fib = fibGenerator()
for n in range(20):
    fibonaccinumbers.append(next(fib))

Instead of iterating over a range and calling next on the generator manually, you then can also just use the take-recipe from itertools to do it just like this:

fibonaccinumbers = take(20, fibGenerator())

On generators

Still not too sure what the generator does however.

A generator is a Python function which generates a sequence of return values. The values are generated lazily, that means when you request it. You create a generator by simply using yield instead of return. A yield will “return” a value and pause the generator. The next time you request a value, the generator will continue where it left off.

Using a generator allows you to create an endless sequence. As you see in the definition of fibGenerator above, there is a endless while-loop which has a yield inside. As the generator stops, it won’t hang up despite that loop.

Here is a quick self-explanationary example:

>>> def example():
    print('begin')
    i = 0
    while True:
        print('Calculating next value')
        yield i
        i += 1

>>> g = example()
>>> next(g)
begin
Calculating next value
0
>>> next(g)
Calculating next value
1
>>> next(g)
Calculating next value
2
>>> next(g)
Calculating next value
3
>>> next(g)
Calculating next value
4

The next function is the built-in function that requests the next value from the iterable. An iterable is anything you can iterate (e.g. for x in iterable: ...); and any generator is also an iterable.