Closures outer() scope def outer(): x = 10 captured variable inner() scope def inner(): return x + 5 reaches back! return inner returns inner fn x = 10 still alive! closure outer() returned scope gone... but x lives on! f = outer() f() → 15 ✓ inner function + free variable = closure captured variable lives as long as the inner function does