A closure is a function object that remembers values from the enclosing lexical scope even after the enclosing function has returned. In Python, closures arise naturally when a nested function references variables from its enclosing function. The inner function "closes over" those variables, keeping them alive even after the outer function has finished executing.
A classic example is a function factory: def make_multiplier(n): return lambda x: x * n. Calling double = make_multiplier(2) creates a closure where the lambda remembers that n is 2. The captured variables are stored in the closure's __closure__ attribute as a tuple of cell objects. You can inspect them, but modifying captured variables requires the nonlocal keyword.
Closures are the foundation of many Python patterns including decorators, callback registries, and partial application (though functools.partial is often clearer). They interact with the LEGB rule's Enclosing scope. A common gotcha is the "late binding closure" problem in loops: [lambda: i for i in range(5)] creates five lambdas that all return 4, because they all close over the same variable i whose final value is 4. The fix is to use a default argument: lambda i=i: i.
Discussed in:
- Chapter 5: Functions — Closures