Recursion is a programming technique where a function calls itself, directly or indirectly, to solve a problem. It allows us to break down complex problems into smaller, identical sub-problems.
Every recursive function must contain two essential components to execute correctly:
- Base Case: The condition under which the function stops calling itself. Without a base case, the function will execute infinitely, leading to a stack overflow.
- Recursive Case: The part of the function where it calls itself with modified (usually smaller/simpler) inputs, moving closer to the base case.
Let's look at a simple countdown example.
def countdown_iterative(n):
while n > 0:
print(n)
n -= 1
print("Blastoff!")Input:
def countdown_recursive(n):
# 1. Base Case
if n <= 0:
print("Blastoff!")
return
# 2. Work done in current step
print(n)
# 3. Recursive Case (calls itself with n-1)
countdown_recursive(n - 1)
countdown_recursive(3)Output:
3
2
1
Blastoff!
When a function is called, Python creates an activation record (or stack frame) and pushes it onto the Call Stack.
- In recursion, each self-call adds a new frame to the stack.
- The stack keeps growing until the base case is reached.
- Once the base case is reached, the functions start returning, popping frames off the stack in LIFO (Last In, First Out) order.
1. STACK GROWTH (Pushing frames):
┌────────────────────────────────────────────────────────┐
│ [ countdown_recursive(0) ] -> Base Case reached! │
│ [ countdown_recursive(1) ] │
│ [ countdown_recursive(2) ] │
│ [ countdown_recursive(3) ] │
└────────────────────────────────────────────────────────┘
2. STACK RESOLUTION (Popping frames after return):
┌────────────────────────────────────────────────────────┐
│ [ countdown_recursive(0) ] -> Returns, pops off │
├────────────────────────────────────────────────────────┤
│ [ countdown_recursive(1) ] -> Returns, pops off │
├────────────────────────────────────────────────────────┤
│ [ countdown_recursive(2) ] -> Returns, pops off │
├────────────────────────────────────────────────────────┤
│ [ countdown_recursive(3) ] -> Returns, pops off │
└────────────────────────────────────────────────────────┘
If you forget to write a base case, or if the recursive step never meets the base case, the program will call itself endlessly. Python prevents this from crashing your computer by setting a limit on how deep the call stack can go.
If this limit is exceeded, Python raises a RecursionError.
Input:
def infinite_hello():
return infinite_hello()
try:
infinite_hello()
except RecursionError as e:
print("Error caught successfully:", e)Output:
Error caught successfully: maximum recursion depth exceeded
Note
The default recursion limit in Python is usually 1000. You can check or change it using sys.getrecursionlimit() and sys.setrecursionlimit(), though increasing it too much can cause a real stack overflow crash.