What Is Recursion in Python?

Recursion in Python means a function calls itself.

This may sound strange at first, but the idea is simple: the function keeps solving a smaller version of the same problem until it reaches a stopping point.

A recursive function has two main parts:

  • Base case: the condition that stops the function
  • Recursive case: the part where the function calls itself again

Here is the simplest working example:

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

countdown(3)

Output:

3
2
1
Done

How this works:

  • if n == 0: is the base case
  • countdown(n - 1) is the recursive call
  • Each call uses a smaller value, so the function moves toward stopping

If you are new to functions, see what is a function in Python.

What recursion means

Recursion is when a function calls itself.

A recursive function usually works like this:

  • It handles one small part of the problem
  • Then it calls itself to handle the rest
  • Each call should get closer to stopping

This is why recursion is often used for problems that can be broken into smaller versions of the same task.

For example, counting down from 3 to 0 can be seen as:

  • print 3
  • count down from 2
  • print 2
  • count down from 1
  • print 1
  • count down from 0
  • stop

The two required parts

A recursive function needs both of these parts:

  • Base case: the condition that stops the recursion
  • Recursive case: the part where the function calls itself

Without a base case, the function will keep calling itself until Python raises an error such as RecursionError: maximum recursion depth exceeded.

Example:

def countdown(n):
    if n == 0:          # base case
        print("Done")
        return
    print(n)
    countdown(n - 1)    # recursive case

The key idea is that the recursive call must move toward the base case.

How recursion works step by step

Let’s walk through countdown(3).

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

countdown(3)

Step by step:

  1. countdown(3) prints 3
  2. It calls countdown(2)
  3. countdown(2) prints 2
  4. It calls countdown(1)
  5. countdown(1) prints 1
  6. It calls countdown(0)
  7. countdown(0) reaches the base case and prints Done
  8. The function calls then finish one by one

In other words:

  • The function starts with one input value
  • It calls itself with a smaller value
  • This repeats until the base case is reached
  • Then the calls return back up

Simple beginner examples

Countdown from a number to zero

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

countdown(5)

This is a good first recursion example because it is easy to follow.

Factorial of a number

A factorial multiplies a number by all positive integers below it.

For example:

  • 4! = 4 × 3 × 2 × 1
  • so the result is 24

Recursive version:

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

print(factorial(4))

Output:

24

What happens here:

  • The base case is n == 1
  • The recursive case is n * factorial(n - 1)

Walking through nested data structures

Recursion is often useful when data contains smaller versions of itself.

Example with a nested list:

def print_items(items):
    for item in items:
        if isinstance(item, list):
            print_items(item)
        else:
            print(item)

data = [1, [2, 3], [4, [5, 6]]]
print_items(data)

Output:

1
2
3
4
5
6

This works because when the function finds another list, it calls itself again to process that smaller list.

When recursion is useful

Recursion is useful when a problem naturally repeats in smaller versions.

Common examples include:

  • Tree-like structures
  • Nested lists
  • Folder and file structures
  • Problems where each step looks like the previous step

Recursion can also make some code easier to read than a loop, especially when the data is nested.

Still, recursion is not always the best choice. For many simple repeated tasks, Python while loops explained will be easier to understand.

When beginners should avoid recursion

Beginners should be careful with recursion in these situations:

  • Simple counting tasks are often easier with loops
  • Deep recursion can hit Python’s recursion limit
  • Recursive code can be harder to debug at first

For example, if you just need to repeat something 10 times, a loop is usually clearer than a recursive function.

If you want to compare the two ideas, it helps to understand what is a loop in Python and Python functions explained.

Common recursion problems

These are the most common beginner mistakes with recursion:

  • Forgetting the base case
  • Writing a base case that is never reached
  • Changing the value in the wrong direction
  • Calling the function with the same value again
  • Expecting recursion to be faster than loops

Here is an example of a broken recursive function:

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

This keeps calling itself forever because there is no base case.

Here is another common mistake:

def countdown(n):
    if n == 0:
        print("Done")
        return
    print(n)
    countdown(n + 1)

This is wrong because n + 1 moves away from the base case instead of toward it.

If your code is not working, these quick checks help:

  • Make sure there is a base case
  • Make sure the base case can actually happen
  • Make sure each recursive call reduces the problem
  • Ask whether a loop would be simpler

Useful debugging tools:

print(n)
print("calling with:", n)

You can also use:

  • help()
  • traceback.print_exc()

FAQ

Is recursion the same as a loop?

No. Both repeat work, but recursion uses function calls while loops use statements like for and while.

What is a base case in recursion?

It is the stopping condition that prevents the function from calling itself forever.

Why does Python give a recursion error?

Usually because the function keeps calling itself too many times or never reaches the base case.

Should beginners use recursion?

Yes, to understand the idea. But for many simple tasks, loops are easier to write and debug.

See also