Base Case, Recursive Case and the Call Stack
18 min · Intermediate
Need help? Ask a tutor on WhatsApp (opens in a new tab)A recursive function solves a problem by solving a smaller copy of the same problem. Two parts keep it correct: a base case that stops the chain and a recursive case that shrinks the input. Python also keeps a call stack that records the waiting calls.
A function that calls itself
Recursion is when a function solves a problem by calling itself on a smaller version of the same problem, until the problem is small enough to answer directly.
A countdown prints a number, then needs the countdown from the number below it. A function can do that by calling itself with a smaller number.
def countdown(n): if n == 0: print("Go!") return print(n) countdown(n - 1)
countdown(3)Example 1 · Before or after the call
def show(n): if n == 0: return print("down", n) show(n - 1) print("up", n)
show(3)down 3 down 2 down 1 up 1 up 2 up 3
What this code does
- Lines before the recursive call run on the way down.
- Lines after it run on the way back up, in reverse order.
Each call handles one number and hands the rest to a new call. The call with 0 ends the chain.
Base case and recursive case
Base case and recursive case are the two parts of every recursive function. The base case returns an answer with no further call. The recursive case calls the function again on a smaller input.
The total of the first n orders is n plus the total of the first n - 1. That chain needs a place to stop.
def total_to(n): if n == 0: return 0 return n + total_to(n - 1)
print(total_to(4))Example 2 · Factorial
def factorial(n): if n <= 1: return 1 return n * factorial(n - 1)
for n in (0, 1, 5, 10): print(n, factorial(n))0 1 1 1 5 120 10 3628800
What this code does
- The base case covers 0 and 1, so no input skips past it.
- Python integers never overflow, so even large factorials stay exact.
Example 3 · Sum of digits
def digit_sum(n): if n < 10: return n return n % 10 + digit_sum(n // 10)
print(digit_sum(4821))15
What this code does
n % 10is the last digit andn // 10is the number without it.- A one-digit number is the base case.
The if is the base case and the last line is the recursive case. The argument shrinks each time, so the base case is always reached.
The call stack
Call stack is the pile of function calls that are waiting to finish. A new call goes on top and the top call finishes first, so the most recent call is always answered first.
Each call waits for the call below it to finish. Python keeps the waiting calls in a pile and finishes the newest one first.
def total_to(n, depth=0): pad = " " * depth print(pad + "call", n) if n == 0: return 0 result = n + total_to(n - 1, depth + 1) print(pad + "return", result) return result
total_to(3)Calls go down to 0 first. Then the answers come back up, newest call first. Every waiting call uses memory, so depth costs space.
No base case, no end
RecursionError is the exception Python raises when the call stack grows deeper than the recursion limit. It usually means a missing base case or an input that never shrinks toward it.
If the base case is missing or never reached, calls keep piling up. Python stops them with an error instead of running forever.
def broken(n): return n + broken(n - 1)
try: broken(5)except RecursionError: print("Stopped: too many calls")Example 4 · A base case that is skipped
def bad(n): if n == 0: return 0 return n + bad(n - 1)
def good(n): if n <= 0: return 0 return n + good(n - 1)
try: bad(-1)except RecursionError: print("bad(-1) never reaches 0")print(good(-1), good(4))bad(-1) never reaches 0 0 10
What this code does
- For -1 the argument moves away from 0, so
badnever stops. - Testing
n <= 0catches every input at or below the base.
Before running a recursive function, ask whether every call moves closer to the base case.
Next step
Check your understanding
10 quick questions