Contact
Evil Genius SocietyHomeLearnForumLeaderboardSocialsMessages
← Back to module

Lesson 8 of 10

A recursive function is one that calls itself. It sounds circular, but it works because each call handles a slightly smaller problem until the problem becomes trivial.

def countdown(n):
    if n == 0:
        print("Liftoff!")
        return
    print(n)
    countdown(n - 1)

countdown(3)

The two required parts

Every recursive function needs both of these:

  1. A base case — a condition where it stops calling itself. Here, n == 0.
  2. A recursive case — a call to itself with an input closer to the base case. Here, countdown(n - 1).

Miss the base case and you get infinite recursion, which crashes with RecursionError: maximum recursion depth exceeded:

def broken(n):
    print(n)
    broken(n - 1)

Python stops it after about a thousand calls rather than letting it run forever.

A classic: factorial

The factorial of 5 is 5 × 4 × 3 × 2 × 1. Notice that 5! = 5 × 4! — the problem contains a smaller version of itself, which is the signal that recursion might fit.

def factorial(n):
    if n <= 1:
        return 1
    return n * factorial(n - 1)

print(factorial(5))

Trace it: factorial(5) returns 5 * factorial(4), which returns 4 * factorial(3), and so on down to factorial(1) returning 1. Then the whole chain multiplies back up: 1, 2, 6, 24, 120.

Recursion versus loops

Anything recursion can do, a loop can do too:

def factorial_loop(n):
    result = 1
    for i in range(2, n + 1):
        result *= i
    return result

print(factorial_loop(5))

The loop is faster and uses less memory, because each recursive call keeps a stack frame around until it finishes.

So when is recursion the right call? When the data itself is nested — file trees, nested dictionaries, category hierarchies. Walking a tree with a loop means managing your own stack of pending items; recursion lets the language do it for you.

def total(items):
    result = 0
    for item in items:
        if isinstance(item, list):
            result += total(item)
        else:
            result += item
    return result

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

isinstance(item, list) checks whether something is a list. That nested structure has no fixed depth, so a plain loop can't handle it — recursion can.

Try it yourself

Write factorial(n) recursively and print the factorial of 5 and 6.

Checkpoint

  • Recursion means a function calls itself on a smaller input.
  • You need a base case to stop, and a recursive case that moves toward it.
  • Without a base case you hit RecursionError.
  • Loops are usually faster; use recursion when the data is genuinely nested.

Questions about this lesson

Log in to ask a question.