What is a closure in Python, and how does a nested function keep state between calls?
A closure is a function that keeps access to the variables of the scope where it was defined, even after that scope has finished running.
Consider a factory function that creates a counter variable, defines a nested increment function that reads and updates it, and then returns that nested function. When the factory returns, its local scope normally disappears — but the nested function holds a reference to it, so the counter variable stays alive. Each call to the returned function reads and updates that same cell, which is why the counter climbs rather than restarting at zero every time.
The keyword that makes this work is nonlocal. Without it, the statement that updates the counter inside the nested function would be treated as creating a new local variable, and Python would raise an UnboundLocalError. With it, the nested function is explicitly allowed to rebind the name from the enclosing scope.
Two practical points to raise in an interview. A closure keeps its captured variables alive for as long as the closure object exists, so storing closures in a long-lived data structure can keep a surprising amount of memory alive. And closures are the foundation of decorators, of callbacks and of many functional patterns, because they let a function carry context without needing a class.