Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Recursion and the call stack

After this lesson: I can write a recursive function with a base case.

60 min lesson5 commandsEveryday Linux commands lab: the thirty commands engineers type from memory

A function that calls itself

Recursion is when a function solves a problem by calling itself on a smaller version of the same problem. It is the natural way to write many algorithms, including merge sort, and it is the key to the two lessons that follow.

Think of a folder of documents that holds more folders. To count every file, you count the files in this folder, then do the same job in each folder inside it.

By the end of this lesson

Note

I can write a recursive function with a base case.

Key words

WordWhat it meansExample
Recursiona function that calls itself
Base casethe input where it stops and answers directly
Recursive casethe input where it calls itself on a smaller problem
Call stackthe pile of calls that are still waiting
Stack frameone call on the pile, with its own values
Factorialn times every whole number below it down to 14! = 24

The cells students fill in are left blank in this preview.

Every recursion needs a base case

A recursive function has two parts. The base case is an input so small that the answer is known, so the function returns it without calling itself.

The recursive case calls the function on a smaller input and uses the answer. The factorial of 5 is 5 times the factorial of 4, and the factorial of 1 is 1.

Run a recursive factorial

Code: python
# A recursive function calls itself on a smaller problem.
def factorial(n):
    if n <= 1:
        # Base case: stop here.
        return 1
    # Recursive case: n times the factorial of n - 1.
    return n * factorial(n - 1)

print(factorial(5))
# Change 5 to 10 and run again.

Worked example: factorial(4) call by call

CallIt waits forIt returns
factorial(4)4 times factorial(3)24
factorial(3)3 times factorial(2)6
factorial(2)2 times factorial(1)2
factorial(1)Nothing: the base case1

The cells students fill in are left blank in this preview.

Check a factorial with Python

Command
python3 -c "import math; print(math.factorial(10))"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

The call stack holds the waiting calls

When a function calls itself, the first call has not finished. It waits. Python keeps each waiting call in a stack frame on the call stack, a pile where the newest call is on top.

In the table above, four frames are on the pile at the deepest point. Then the top one returns, and the pile shrinks one frame at a time.

Python stops a recursion that goes too deep

Each frame uses memory, so a stack cannot grow for ever. Python allows about 1000 frames by default, then raises an error called RecursionError.

A function with no base case never stops calling itself. The first Run asks for the limit. The second Run starts an endless recursion and shows the last line of the error.

Ask Python for its recursion limit

Command
python3 -c "import sys; print(sys.getrecursionlimit())"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Start a recursion that never stops

Command
python3 -c "exec('def f(n):\n return f(n + 1)\nf(0)')" 2>&1 | tail -n 1

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A recursion can repeat the same work

The Fibonacci numbers start 0, 1, and each next one is the sum of the two before: 0, 1, 1, 2, 3, 5, 8. So fib(n) is fib(n - 1) plus fib(n - 2), and fib(0) and fib(1) are the base cases.

This function calls itself twice, so the number of calls roughly doubles each time n goes up by one.

Run Fibonacci and count the calls

Code: python
# Fibonacci by recursion, counting how many calls it makes.
calls = [0]

def fib(n):
    calls[0] = calls[0] + 1
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print("fib(10) =", fib(10), "calls", calls[0])
# Change 10 to 15 and run again. Watch the calls.

Worked example: calls made by fib(n)

nfib(n)Calls
5515
1055177
206,76521,891
30832,0402,692,537

The cells students fill in are left blank in this preview.

Write the same function to a file

Command
printf 'def fib(n):\n    if n < 2:\n        return n\n    return fib(n - 1) + fib(n - 2)\n\nprint(fib(30))\n' > fib.py

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Run it for n = 30

Command
python3 fib.py

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A common mistake

Warning

Many people think a recursive function stops by itself when the numbers get small. Nothing stops it unless you write a base case that returns without calling again. Always write the base case first, then check that every call moves closer to it.

About this lab and its source: Everyday Linux commands lab: the thirty commands engineers type from memory

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.