Build a Python Fibonacci Sequence Generator (Step-by-Step)

Want to generate the Fibonacci sequence efficiently in Python? This tutorial bridges the gap between basic recursion and professional optimization. You will learn how to move from a slow, naive solution to high-performance code using Dynamic Programming and Generators.

What You Will Learn:

  • The logic behind the Fibonacci sequence
  • Why naive recursion crashes your performance
  • How to use Memoization and Dynamic Programming
  • Writing Pythonic code with Decorators and Generators

Step 1: Understanding the Fibonacci Sequence

The Fibonacci sequence is a series of numbers where each number is the sum of the two preceding ones. It appears frequently in mathematics, nature, and technical interviews.

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

Mathematically, it is defined as (where you're finding the nth Fibonacci number):

F(n) = F(n-1) + F(n-2)

With base cases: F(0) = 0 and F(1) = 1.

The Recursive Approach

The most intuitive way to translate the mathematical definition into code is using Recursion, a technique where a function calls itself to solve smaller instances of the problem. This is often the method used by beginners.

Here is the standard "Naive" implementation:

def fib_naive(n: int) -> int:
    if n <= 1:
        return n
    return fib_naive(n - 1) + fib_naive(n - 2)

The Problem with Naive Recursion

While this code is simple, it is mathematically inefficient. To calculate fib_naive(5), the computer must calculate fib_naive(4) and fib_naive(3). But to calculate the next number, fib_naive(4), it again calculates fib_naive(3). You can see the issue with recursive methods. As you generate higher subsequent numbers, there are redundant calculations.

recursion tree for fib 5 showing redundant calls

As n grows, the number of redundant calculations explodes. This algorithm runs in Exponential Time O(2^n). If you try to run this for n=50, your program might hang for hours.

The Case for Dynamic Programming

To fix the performance issues of recursion, we turn to Dynamic Programming (DP). DP is a method for solving complex problems by breaking them down into simpler subproblems and, crucially, storing the results so we never have to recompute them. You can use this to build a more Pythonic Fibonacci function.

This specific technique is called Memoization (often confused with "memorization").

How Memoization Optimizes Fibonacci:

  • Check Cache: Before computing a value, the function checks if it's already in our dictionary (cache).
  • Compute Once: If it's not in the cache, we compute it.
  • Store Result: We save the result in the cache for future use.

This reduces the time complexity from Exponential O(2^n) down to Linear O(n).

Step 2: Implementing Optimized Recursion

Let's implement a robust solution using a dictionary to store our cache. Note the use of Type Hints to adhere to modern Python standards.

# Cache dictionary to store computed values
fib_cache: dict[int, int] = {}

def fib_memo(n: int) -> int:
    """Computes Fibonacci using recursion and manual memoization."""
    if n in fib_cache:
        return fib_cache[n]
    
    if n <= 1:
        val = n
    else:
        val = fib_memo(n - 1) + fib_memo(n - 2)
    
    fib_cache[n] = val
    return val

The Modern "Pythonic" Way: @functools.cache

In Python 3.9+, you don't need to manually create a dictionary. You can use the built-in @cache decorator, which handles the memoization automatically behind the scenes.

from functools import cache

@cache
def fib_modern(n: int) -> int:
    if n <= 1:
        return n
    return fib_modern(n - 1) + fib_modern(n - 2)

⚠️ Warning on Recursion Depth: Even with memoization, Python has a limit on how many recursive calls can be active at once (usually 1,000). If you try to calculate fib(2000) recursively, your program will crash. For large numbers, use the approaches below.

Step 3: Generating the Full Sequence (The Iterative Approach)

If your goal is to generate the sequence (0, 1, 1, 2...) rather than just the Nth number, using recursion is inefficient. Instead, we use Iteration (loops) or Generators.

1. The Iterative Loop (Fastest & Simplest)

This approach uses a loop to update two variables. It is the most memory-efficient method because it doesn't use a call stack.

def fib_iterative(n: int) -> int:
    """Calculates the Nth number iteratively in O(n) time and O(1) space."""
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a

2. The Python Generator (Best for Sequences)

If you want to list the next Fibonacci numbers, don't append them to a list one by one. Use yield to create a Generator. This generates numbers on the fly and saves memory.

from typing import Generator

def fib_generator(n: int) -> Generator[int, None, None]:
    """Yields the Fibonacci sequence up to n terms."""
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

# Usage:
print(list(fib_generator(10)))
# Output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Comparison: Which Should You Use?

Time and Space Complexity Analysis

Implementation Time Complexity Space Complexity Best Use Case
Naive Recursion O(2ⁿ) (Exponential) O(n) (Stack) Never (Educational only)
Memoization O(n) (Linear) O(n) (Cache + Stack) When logic is complex and recursive naturally
Iterative / Generator O(n) (Linear) O(1) (Efficient) Production code & large sequences

naive

Wrapping Up

You have now upgraded your simple Fibonacci generator from a basic recursive function to a production-ready Python program.

Key Takeaways:

  • Avoid Naive Recursion: It repeats work and is too slow for n > 30.
  • Use Memoization: When you need to optimize recursive logic.
  • Use Iteration/Generators: The gold standard for performance and generating sequences in Python.

Next Step: Try running the fib_generator code and modifying it to yield Fibonacci numbers infinitely until a certain value (e.g., 1,000,000) is reached!

By Robert Johns

Technical Editor for Hackr.io | 15+ Years in Python, Java, SQL, C++, C#, JavaScript, Ruby, PHP, .NET, MATLAB, HTML & CSS, and more... 10+ Years in Networking, Cloud, APIs, Linux | 5+ Years in Data Science | 2x PhDs in Structural & Blast Engineering

View all post by the author

Subscribe to our Newsletter for Articles, News, & Jobs.

I accept the Terms and Conditions.

Disclosure: Hackr.io is supported by its audience. When you purchase through links on our site, we may earn an affiliate commission.

In this article

Learn More