Skip to content
Laviyx Learn

Try

Python course menu

Python Recursion Explained: Base Case, Recursive Case and Examples

Learn recursion in Python step by step: what a base case and recursive case are, countdown, factorial, Fibonacci, summing and flattening nested lists, the recursion limit, memoization with lru_cache, and recursion vs loops.

Intermediate7 min readUpdated
On this page

A recursive function is a function that calls itself. It solves a problem by breaking it into a smaller version of the same problem, until the problem is small enough to answer directly. Recursion is a natural fit for things that contain smaller copies of themselves: nested folders, family trees, menus within menus.

The two parts of every recursive function#

  1. A base case: a simple situation answered directly, without recursing. This is what stops the recursion.
  2. A recursive case: the function calls itself with a smaller input, moving toward the base case.

A first example: countdown#

Python
def countdown(n):
    if n == 0:              # base case
        print("Lift off!")
        return
    print(n)
    countdown(n - 1)        # recursive case: smaller problem

countdown(3)
Output
3
2
1
Lift off!

Each call handles one number and hands the rest of the work to a new call with n - 1, until n reaches 0.

Factorial#

The factorial of n (written n!) is n × (n−1) × … × 1. Notice that 5! = 5 × 4!: the problem contains a smaller version of itself.

Python
def factorial(n):
    if n <= 1:                    # base case
        return 1
    return n * factorial(n - 1)   # recursive case

print(factorial(5), factorial(1), factorial(10))
Output
120 1 3628800

How factorial(4) unfolds:

Text
factorial(4) = 4 * factorial(3)
             = 4 * (3 * factorial(2))
             = 4 * (3 * (2 * factorial(1)))
             = 4 * (3 * (2 * 1))
             = 24

Each call waits for the one below it to return, then finishes its own multiplication.

Recursion on lists#

Sum a list as "the first item plus the sum of the rest":

Python
def total(numbers):
    if not numbers:                          # base case: empty list
        return 0
    return numbers[0] + total(numbers[1:])   # recursive case

print(total([4, 8, 15, 16]))
Output
43

Recursion really shines on nested data, where a loop alone cannot know how deep to go:

Python
def flatten(items):
    result = []
    for item in items:
        if isinstance(item, list):
            result.extend(flatten(item))   # dive into the inner list
        else:
            result.append(item)
    return result

print(flatten([1, [2, [3, 4]], [5], 6]))
Output
[1, 2, 3, 4, 5, 6]

Fibonacci and repeated work#

Each Fibonacci number is the sum of the two before it:

Python
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print([fib(i) for i in range(10)])
Output
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

This is elegant but very slow for large n, because the same values are recalculated over and over: fib(30) makes over a million calls. Memoization caches results so each value is computed once:

Python
from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(80))
Output
23416728348467685

@lru_cache is a decorator that remembers previous results.

The recursion limit#

Without a base case (or with a base case that is never reached), a function calls itself until Python stops it:

Python
def forever(n):
    return forever(n + 1)

forever(0)
Output
RecursionError: maximum recursion depth exceeded
Python
import sys
print(sys.getrecursionlimit())
Output
1000

Python limits recursion to about 1,000 nested calls by default, to protect against crashes. For problems that need deeper recursion (such as summing a list of 100,000 items), use a loop instead.

Recursion or a loop?#

Recursion is a good fit for…A loop is better for…
tree-shaped or nested data (folders, JSON, menus)simple repetition over a list or range
problems naturally defined in terms of themselvesvery large inputs (no depth limit)
divide-and-conquer algorithms (merge sort, quicksort)performance-critical code

Common mistakes#

Practice#

Practice exercise

Write a recursive function digit_sum(n) that returns the sum of the digits of a non-negative integer: digit_sum(4815) should return 18.

Show hint

The base case is a single-digit number. Otherwise, add the last digit (n % 10) to the digit sum of the rest (n // 10).

Show solution
Python
def digit_sum(n):
    if n < 10:
        return n
    return n % 10 + digit_sum(n // 10)

print(digit_sum(4815), digit_sum(7))
Output
18 7

4815 → 5 + digit_sum(481) → 5 + 1 + digit_sum(48) → 5 + 1 + 8 + 4 = 18.

Key takeaway#

Finished this lesson?