How the Call Stack Works —
Every function call. Every return.
Every time you call a function, Python pushes a frame onto the call stack. Every time that function returns, the frame pops off. Recursion crashes with RecursionError when the stack gets too deep. Watch frames push and pop on LearnBug as your code runs — and every mystery about function calls, local variables, and recursion disappears.
What is the Call Stack?
The call stack is a stack data structure maintained by the Python runtime that tracks which function is currently executing and where to return when it finishes. Each entry is a stack frame — it holds the function name, its local variables, and the return address. Frames are pushed on call and popped on return, following LIFO (Last In, First Out) order.
Why visualization changes everything
Most developers understand functions individually but lose track of what happens when functions call other functions — especially recursively. On LearnBug, the call stack grows upward as functions call each other, and shrinks as they return. Local variables are visible inside each frame. The concept of "stack overflow" becomes completely concrete when you watch it happen.
Tracing factorial(3) on the call stack
Watch the stack grow as recursion dives deeper, then unwind as each call returns.
Call factorial(3) — push frame
Python pushes a frame for factorial(3). Local variable n = 3. But it needs factorial(2) first — so it calls again.
Call factorial(2) — push another frame
Stack grows. factorial(3)'s frame is paused, waiting for the return. factorial(2) now runs with its own n = 2.
Call factorial(1) — stack at max depth
Three frames deep. factorial(1) hits the base case: n == 1, return 1. No more recursive calls. Now the stack unwinds.
factorial(1) returns 1 — pop frame
factorial(2) receives 1, computes 2 × 1 = 2, returns 2. Its frame pops. Stack shrinks.
factorial(3) returns 6 — stack empty
factorial(3) receives 2, computes 3 × 2 = 6, returns 6. Its frame pops. Call stack is empty. Final answer: 6.
What happens when the stack gets too deep
RecursionError: maximum recursion depth exceeded
Python's default recursion limit is 1000 frames. If your function calls itself without hitting a base case, frames keep pushing until the limit is reached — then Python raises this error. This is a "stack overflow".
# ❌ No base case — infinite recursion
def factorial(n):
return n * factorial(n - 1) # never stops!
# ✅ With base case — stack unwinds correctly
def factorial(n):
if n <= 1: # base case stops recursion
return 1
return n * factorial(n - 1)Inspecting the call stack in Python
import sys
import traceback
# Check current recursion limit
print(sys.getrecursionlimit()) # → 1000 (default)
# Increase if needed (use carefully)
sys.setrecursionlimit(2000)
# Print current call stack from anywhere in your code
traceback.print_stack()
# See stack depth at any point
import inspect
print(len(inspect.stack())) # number of active framesCall Stack — Key Facts
Frequently asked questions
Why are local variables isolated between function calls?
Each stack frame has its own memory region for local variables. When factorial(3) calls factorial(2), the n = 3 in the first frame is completely separate from n = 2 in the second frame. Frames are independent — that's why recursion works. When a frame is popped, its local variables are gone.
What is a stack frame?
A stack frame (also called an activation record) is the block of memory the runtime allocates for a single function call. It stores: the function's local variables, the parameters passed in, the return address (where to resume after the function returns), and a reference to the previous frame. Python's inspect.stack() lets you examine frames at runtime.
How is the call stack different from the heap?
The call stack stores function frames — temporary, short-lived data tied to function execution. The heap stores objects allocated dynamically (lists, dicts, class instances in Python) — longer-lived data managed by the garbage collector. In Python, local variable names live on the stack but the objects they point to live on the heap.
Can I convert recursion to iteration to avoid stack overflow?
Yes. Any recursive algorithm can be rewritten iteratively using an explicit stack (a Python list used as a stack). Instead of the runtime managing frames, you push and pop your own state onto a list. This removes the 1000-frame limit and often reduces memory usage. The trade-off is that iterative code is sometimes less readable than recursive.
What is tail recursion and does Python optimise it?
Tail recursion is when the recursive call is the very last operation in a function — no computation after the return. Languages like Haskell and Scala optimise this to reuse the same stack frame instead of pushing a new one, avoiding stack overflow. Python does NOT perform tail call optimisation by design — Guido van Rossum intentionally kept stack traces readable. In Python, deep tail recursion still risks RecursionError.
Watch your function frames push and pop in real time
Paste any recursive function into LearnBug and see the call stack grow and shrink with every call and return.