ProgrammingPython Developer

How does Python implement the mechanism of working with nested functions (closures)? What are closures used for, what pitfalls exist, and how to correctly modify variables of an outer function?

Pass interviews with Hintsage AI assistant

Answer.

In Python, a closure is a function that "remembers" the values of external variables even if it is called outside their scope. Closures are created when an inner function refers to variables defined in an outer function. To modify such variables from the nested function in Python 3, the keyword nonlocal is used.

Example:

def make_accumulator(): total = 0 def add(value): nonlocal total total += value return total return add acc = make_accumulator() print(acc(10)) # 10 print(acc(5)) # 15

Without nonlocal, the variable total would be inaccessible for modification (UnboundLocalError).

Trick Question.

Question: "Can we increase the variable from the outer function inside the nested function without the nonlocal keyword?"

Answer: No, without nonlocal this will lead to an error as the interpreter will consider the variable local to the nested function. Example:

def outer(): count = 0 def inner(): count += 1 # UnboundLocalError return count return inner

Examples of real errors due to lack of understanding of the nuances of the topic.


Story In one web application, they wanted to implement a counter locally for each handler through nested functions, but forgot to use nonlocal. The counter always returned 1, since it counted count in the local scope and incremented a new one, not associated with the outer closure.


Story In multithreading tasks, closures and lambdas are often used. Without understanding closures, a situation arose where all lambda functions "remembered" the last value of the loop variable, and the tasks copied each other instead of processing different tasks.


Story When writing a decorator without using the correct closure (parameters were not passed to the outer scope), a situation arose where the decorator could not accumulate state between calls, which led to unexpected results and unstable application behavior.