Phase: 4. Functions | Estimated time: 2 hours | Milestone Project: No
- Module 031 (Functions: Basics)
- Module 033 (Scope and Namespaces)
By the end of this module, you will be able to:
- Write recursive functions with a base case and recursive case
- Implement factorial and Fibonacci recursively
- Compare recursion vs iteration
- Understand Python's recursion stack depth limit
- Visualize recursion trees
- Explain the concept of tail recursion
Recursion is a powerful technique for problems that have a self-similar structure (trees, graphs, divide-and-conquer algorithms). Understanding recursion deepens your grasp of function calls and the call stack.
A function is recursive if it calls itself. Every recursive function needs:
- Base case — stops the recursion.
- Recursive case — calls itself with a smaller or simpler input.
def factorial(n: int) -> int:
"""Calculate n! recursively.
Args:
n: A non-negative integer
Returns:
n! (n factorial)
"""
if n <= 1:
return 1 # base case
return n * factorial(n - 1) # recursive casefactorial(4)
│
└── 4 * factorial(3)
│
└── 3 * factorial(2)
│
└── 2 * factorial(1)
│
└── 1 (base case)
def fibonacci(n: int) -> int:
"""Return the nth Fibonacci number.
Args:
n: Position in Fibonacci sequence
Returns:
The nth Fibonacci number
"""
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)| Aspect | Recursion | Iteration |
|---|---|---|
| Code style | Elegant, declarative | Explicit loop control |
| Memory | Uses call stack (risk of overflow) | Usually O(1) extra space |
| Performance | Slightly slower (function call overhead) | Faster |
| Best for | Tree/graph traversal, divide-and-conquer | Simple linear tasks |
Python limits recursion depth (default ~1000) to prevent stack overflow:
import sys
print(sys.getrecursionlimit()) # 1000
sys.setrecursionlimit(2000) # increase (not recommended for production)A recursive call is tail-recursive if it's the last operation in the function. Python does NOT optimize tail recursion, but the concept is important:
def factorial_tail(n: int, acc: int = 1) -> int:
"""Tail-recursive factorial (conceptual — Python doesn't optimize)."""
if n <= 1:
return acc
return factorial_tail(n - 1, acc * n)- Missing base case — infinite recursion leads to
RecursionError. - Base case never reached — make sure input shrinks toward the base case.
- Stack overflow — Python's recursion limit is ~1000; use iteration for deep recursion.
- Inefficient recursion — Fibonacci without memoization is exponential (O(2^n)).
- Write
factorial(n)recursively and test with n=5. - Write
fibonacci(n)recursively and test with n=10. - Write a recursive
countdown(n)function that prints n, then calls itself with n-1. - Use a loop to see at what n you get a RecursionError.
- Recursion = base case + recursive case.
- The call stack grows with each recursive call.
- Python has a recursion limit (~1000).
- Not all problems are best solved recursively — consider iteration for deep recursion.
- Tail recursion is a concept; Python doesn't optimize it.
Continue to Module 036: Higher-Order Functions (map, filter, reduce).