Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Data Structures, Lightly  ›  Lesson

Recursion

Recursion 13 minA function that calls itself on a smaller problem, and the call stack that keeps track of every waiting call
Your task
Write sum_digits(n) recursively. Add up the digits of a non-negative integer n. Base case: a single digit returns itself. Otherwise, n % 10 peels off the last digit and n // 10 is everything else. Example: sum_digits(1234) -> 10.

Recursion

In short: a recursive function solves a problem by calling itself on a smaller version of the same problem, until a base case is small enough to answer directly — no more calls. Every call gets its own frame on the call stack, with its own local variables, completely separate from the frame that called it. Frames stack up while the calls go deeper, then pop off and return, one at a time, in reverse order — which is also why recursion without a base case doesn't loop forever quietly, it crashes with RecursionError once the stack runs out of room (Python's default limit is about 1000 frames deep). The DSA course builds whole algorithm families on top of this; here it's just the base-case-and-stack mechanics.

A staircase of five boxes labelled factorial(5), factorial(4), factorial(3), factorial(2), factorial(1) stacking upward, factorial(1) marked "base case — returns 1, no further call"; then the same five boxes collapsing back down the other side, each one multiplying in its own number as it returns: 1, then 2, then 6, then 24, then 120

Price a gift hamper of nested boxes

A gift-wrapping service prices a hamper where boxes can hold smaller boxes, which can hold smaller boxes still, to any depth. factorial is the simplest version of the same shape — each call waits for the one it made, then does one more multiplication before handing its own answer back up:

python

Step through it and watch the calls pile up before any of them return:

step through it
1def factorial(n):
2 if n <= 1:
3 return 1
4 result = n * factorial(n - 1)
5 return result
6 
7print(factorial(4))

factorial(4) can't finish its multiplication until factorial(3) returns a value — which can't finish until factorial(2) returns — all the way down to factorial(1), the base case, which returns 1 with no further call. Then every waiting multiplication resolves, one level at a time, on the way back up: 1, then 2, then 6, then 24. The mistake people make reading this code for the first time is assuming the multiplications happen on the way down — they don't. Nothing multiplies until the base case is hit and the unwinding starts.

Compute compound interest, year by year

A savings calculator figures out a balance after n years of compounding, where each year's answer depends on the year before it — exactly the shape recursion solves, with each call carrying its own n completely separately from every other call:

What does this print?
def countdown(n):
    if n == 0:
        return ["liftoff"]
    return [n] + countdown(n - 1)

print(countdown(3))

Two different calls to countdown never share one n — countdown(3)'s local n is 3 for its entire lifetime, even though it's sitting on the stack waiting on countdown(2), whose own n is 2 in a completely separate frame. That independence is what makes recursion safe at all: if every call shared the same variables, this would break the moment two calls were alive at once.

Flatten a company's reporting chain

A company's org chart is a manager with direct reports, who may themselves manage more people, to any depth — there's no fixed number of levels to loop over, which is exactly where recursion earns its keep over a loop. The mistake that breaks recursive code most often, though, isn't the recursive step — it's forgetting the base case, or writing one that's never actually reached, so the calls never stop on their own:

broken — fix itRecursionError

Run it and watch it crash. Then make it print 1 through 5 and stop.

Every working recursive function needs two things: at least one case that returns without recursing (the base case), and a guarantee that every recursive call moves strictly closer to it. count_up has neither — n only ever grows, so no condition ever stops it, and Python eventually refuses to add one more frame.

Quick practice

What does this print?
def mystery(n):
    if n == 0:
        return 0
    return n + mystery(n - 1)

print(mystery(4))
What does this print?
def countdown(n):
    if n == 0:
        return ["liftoff"]
    return [n] + countdown(n - 1)

print(countdown(0))

🎯 Your turn

Write sum_digits(n) recursively. Add up the digits of a non-negative integer n:

  • sum_digits(1234) → 10 (1+2+3+4)
  • sum_digits(5) → 5

Hint — the base case is a single digit: if n < 10: return n. Otherwise, n % 10 peels off the last digit and n // 10 is everything else — return n % 10 + sum_digits(n // 10).

Press ▶ Run, try the Live App chips, then ✓ Check. After that, the practice set below counts down, raises to a power, and flattens a nested list — recursion's natural shape.

Practice — level up

0/5 solved

Solve each in its own editor — Run to try, Check to grade. Stuck? Reveal a Hint, or the full Solution + walkthrough.

Warm-upCount down to zero

Write count_down(n) returning the list [n, n-1, ..., 0], built recursively (no loop).

recursionbase-case
DrillExponentiation, recursively

Write power(base, exp) computing base ** exp recursively (no **, no loop), for a non-negative exp.

recursionbase-case
BuildHow many digits?

Write digit_count(n) returning how many digits a non-negative integer n has, recursively.

recursionbase-case
BossA palindrome, checked from the outside in

Write is_palindrome(s) checking whether s reads the same forwards and backwards, recursively: compare the first and last characters, then recurse on what's left between them.

recursionbase-case
CapstoneFlatten a nested list

Write flatten(nested), returning a flat list containing every non-list value in nested, however deeply the lists are nested inside each other.

recursion
sum_digits.py
Call the function you wrote — just like your app's frontend would. Edit the inputs and hit Call.
sum_digits(n) → intAdd up every digit of n, recursively.
try:
returned
No app map for this section yet.
Press Run to execute your code.
Press Check to run the tests for this lesson.