Stacks — Visual Learning

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.

LIFOLast In First Out
O(n)Recursion depth
PythonLanguage

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.

YouTube — Call Stack Explained Visually
📺 Drop your YouTube embed here
LearnBug — frames pushing and popping in real time
🖼 Add a LearnBug screenshot here
Walkthrough

Tracing factorial(3) on the call stack

Watch the stack grow as recursion dives deeper, then unwind as each call returns.

1

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.

factorial(3)n = 3
Stack base
2

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.

factorial(2)n = 2
factorial(3)n = 3 — waiting
Stack base
3

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)n = 1 → return 1
factorial(2)n = 2 — waiting
factorial(3)n = 3 — waiting
Stack base
4

factorial(1) returns 1 — pop frame

factorial(2) receives 1, computes 2 × 1 = 2, returns 2. Its frame pops. Stack shrinks.

factorial(2)n = 2 → 2 × 1 = 2
factorial(3)n = 3 — waiting
Stack base
5

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.

factorial(3)n = 3 → 3 × 2 = 6 ✓
Stack base
Stack Overflow

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".

PythonMissing base case → 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)
Python Code

Inspecting the call stack in Python

PythonUsing traceback and sys to inspect stack depth
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 frames

Call Stack — Key Facts

Push (call)O(1)Adding a frame to the top of the stack is constant time
Pop (return)O(1)Removing the top frame is constant time
Space (recursion depth n)O(n)n recursive calls = n frames on the stack simultaneously
Python default limit1000 framesExceeding it raises RecursionError — not a crash, a controlled error

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.

Open Playground →