Recursion
- Write recursive functions with clear base cases
- Recognize when recursion is clearer than iteration
- Avoid stack overflow with tail-call awareness
- Convert simple recursion to iteration when needed
Python caps recursion at ~1000 frames (sys.getrecursionlimit), so tree traversals in AST tooling, JSON walkers, and directory scanners often need iterative rewrites. functools.lru_cache on recursive functions is the standard interview trick for memoization.
- Missing or wrong base case — you'll hit
RecursionErrorfast; write the base case first, then the recursive step. - Deep recursion on user input — an attacker can crash your parser; convert to a stack-based loop for JSON/XML.
- Recomputing overlapping subproblems — wrap the function with
@lru_cache(maxsize=None)for instant speedup.
A function that calls itself. Every recursion has two parts:
- Base case — when do we stop?
- Recursive case — call ourselves with a smaller subproblem.
When it shines
- Tree / graph traversals
- Anything naturally defined "in terms of itself" (factorial, fib, parsers)
- Quick & dirty divide-and-conquer
Pitfalls
- Forgetting the base case →
RecursionError - Python's default recursion limit is ~1000; deep recursion needs
sys.setrecursionlimitor an iterative rewrite.
Try it
- Write a recursive
flatten([1, [2, [3, 4]]])→[1, 2, 3, 4]. - Use recursion to reverse a list.
3 graded exercises
Write the code, click Check. We’ll tell you exactly what to fix.
- Exercise 1
Write recursive
factorial(n)— base casen <= 1returns1, elsen * factorial(n - 1). Printfactorial(6). Expected:720. - Exercise 2
Write recursive
flatten(nested)that takes a nested list (any depth) and returns a flat list. Test withflatten([1, [2, [3, [4, 5]]], 6])— expected:[1, 2, 3, 4, 5, 6]. - Exercise 3
Write recursive
power(base, exp)for non-negativeexp— base caseexp == 0returns1, elsebase * power(base, exp - 1). Printpower(2, 10). Expected:1024.