Why won't this code display the fibonacci sequence

This code only displays 5 ones (with calculation limit being 5)


calculationLimit = int(input("Type in limit"))

def fibonacciSequence(current, previous):
    next = current + previous
    previous = current
    current = next
    print(next)

for i in range(0, calculationLimit):
    fibonacciSequence(1, 0)
    i =+ 1

How do I make it display the fibonacci sequence?
Thanks,
zm476

You either need to iterate (for or while loop) or use recursion within your function. The way you’re calling fibonacciSequence now, the only arguments it ever sees are zero and one.

Skip has pointed out the core problem with your code (always calling the
function with 0 and 1).

However there are a few other remarks worth making:

 def fibonacciSequence(current, previous):
     next = current + previous
     previous = current
     current = next
     print(next)

Another thing to note is that variable in functions are local, and
vanish when the function returns. This means that when you update
previous and current in the middle of this function, those updates
are discarded when the function finishes (because the variables
themselves are discarded).

If this code was inline in the loop body it would be effective, because
you’d be using the same variables throughout.

 for i in range(0, calculationLimit):
     fibonacciSequence(1, 0)
     i =+ 1

The range() function returns values for i and the for-loop assigns
them to i. There’s no need to increment i at the bottom of the
loop.

Now, in normal code it is very common to break operations out into
functions. But because functions discard their local variables on
return, in order to have those functions change state (eg current and
previous) the usual thing is to have the function return the updated
values. The calling code (your loop body) would pass in the values for
the function to work on, and receive updated values back from the
function so that they can be used in the next call.

Cheers,
Cameron Simpson cs@cskk.id.au

Because fibonacciSequence(1, 0) means to start over again, using 1 as the value of current and 0 as the value of previous, no matter what happened any other time that the function was called. Assigning inside the fibonacciSequence back to current and previous doesn’t change anything outside the function. It wouldn’t even if we used variable names for the call - the function only “sees” values, not variables, being passed in.

In order to have an effect outside the function like that, we would need to pass an object that can be modified, and modify it. There is no way to modify an integer - 1 means 1 no matter what math you do, and if you calculate another number, it’s a different object.

To fix the problem, the natural way is to either use the loop inside the function, or else return them for the outside code to use.

As an aside, the code i =+ 1 doesn’t do what you presumably want, and is also not relevant. There is no =+ operator; this means the same thing as i = +1, which is the same as i = 1. But it also doesn’t matter that we change i here; the for loop will change it back each time. It’s important to understand that range is not part of the for loop syntax; it makes an object that actually “contains” the values that the loop will use. (But in a special way, that doesn’t need to actually store them all in memory at once.) for i in means that i will be set to another value from the source, each time through the loop.

It quite normal for neebee to get into troubles. So you should get a little bit debug skill.
The most basic skill is print every thing like this

calculationLimit = int(input("Type in limit"))

def fibonacciSequence(current, previous):
    next = current + previous
    print('next: ', next)
    previous = current
    print('previous: ', previous)
    current = next
    print('current: ', current)
    print(next)

for i in range(0, calculationLimit):
    fibonacciSequence(1, 0)
    i =+ 1
    print('i: ', i)

And you can see i =+ 1 not working actually, and the params for function fibonacciSequence not change.

the correct version is below

def fibonacciSequence(current_num, previous_num):
    next_num = current_num + previous_num
    return next_num

previous_num = 0
current_num = 1
for i in range(0, calculationLimit):
    next_num = fibonacciSequence(current_num, previous_num)
    print('next_num: ', next_num)
    previous_num = current_num
    current_num = next_num

PS: The reason I change next to next_num is that next is a keyword in python.

You could also slightly simplify such expressions by using formatted strings instead:

print(f'{previous= }')

Then you wouldn’t need to repeat the variable names twice (and also could debug arbitrary custom expressions).

Thanks! I don’t know this kind of f-string before.
It seems it works on python3.9 but not on python3.7.
What is the proper name of this kind of f-string?

Self-documenting expressions. They were introduced in 3.8: What’s New In Python 3.8 — Python 3.12.0 documentation

2 Likes

This can all be simplified a bit by using tuple assignment to avoid temporary variables, as well as a few other tweaks (and using proper Python code style):

def fibonacci_sequence(previous, current):
    return current + previous

previous, current = 0, 1
for __ in range(calculation_limit):
    previous, current = current, fibonacci_sequence(previous, current)
    print(current)

Or, if you want previous and current to be “remembered” within fibonacci_sequence, as your original example seems to expect, make it a generator using the yield keyword instead of return:

def fibonacci_sequence(calculation_limit):
    previous, current = 0, 1
    for __ in range(calculation_limit):
        previous, current = current, current + previous
        yield current

Now, you can construct a generator that will iterate over the fibonacci sequence to the limit you set:

fibonacci_generator = fibonacci_sequence(calculation_limit)
for n in fibonacci_generator:
    print(n)

This works much the same way as before, but the real power of this approach is it allows fibonacci_sequence to generate values infinitely, if you remove the limit, while not storing anything but the current and previous value in memory…

def fibonacci_sequence():
    previous, current = 0, 1
    while True:
        previous, current = current, current + previous
        yield current

while being able to be started and stopped as you wish:

fibonacci_generator = fibonacci_sequence()
while True:
    n = int(input("How many more Fibonacci values to print? "))
    for __ in range(n):
        print(next(fibonacci_generator))
1 Like

Your code is neat and clean, pretty pythonic!

The reason I avoid to use tuple assignment and generator is that it seems the OP seems fresh to Python, I don’t what to invoke too much knowledge beyond the original post.
As you see, their’s only functions and variables.

1 Like

Yeah, its smart to limit the concepts to only those required and usually I try to do so; in this case I introduced tuple assignment mostly as a fairly concise, intuitive way to swap two variables, but the generator approach is definitely more advanced then it seems they actually need; I mentioned it more to simply illustrate the point that one can write a function that remembers its state, as they seemed to expect, rather than to suggest they actually use it here.

2 Likes