Understanding Python Closures, Generators, and the nonlocal Keyword with Multiple Implementation Methods
This article explains how to create a counter using Python closures, explores three different implementations—including mutable objects, generators, and the nonlocal keyword—while clarifying the behavior of immutable vs. mutable objects and demonstrating the practical use of nonlocal in nested functions.
On Liao Xuefeng's website a closure exercise is presented: build a function that returns a counter which yields an incrementing integer each call. The article walks through several solutions and explains related concepts such as mutable vs. immutable objects and the nonlocal keyword.
Method One attempts to use a default argument to capture the counter value, but because integers are immutable the result is always 1 . The code shown is:
def createCounter():
i = 0
def counter(i=i):
i = i+1
return i
return counter
# Result: 1 1 1 1 1To fix the immutability issue the article switches to a mutable container (a list) so the inner function can modify the shared state:
def createCounter():
i = [0]
def counter():
i[0] = i[0] + 1
return i[0]
return counter
# Result: 1 2 3 4 5Method Two uses a generator to produce an infinite sequence of integers, letting the inner counter simply return next(f) :
def createCounter():
def inter():
n = 1
while True:
yield n
n = n + 1
f = inter()
def counter():
return next(f)
return counterThis approach leverages the fact that a generator retains its state between calls.
Method Three introduces the nonlocal keyword, allowing the inner function to modify a variable defined in the enclosing scope without using a mutable container:
def creat_counter():
i = 0
def counter():
nonlocal i
i = i + 1
return i
return counterThe article explains that nonlocal tells Python to use the variable from the nearest enclosing function scope, unlike global which refers to the module-level namespace.
Two illustrative examples compare the behavior of a plain nested function (which creates a new local variable) with one that declares nonlocal , showing that the latter updates the outer variable, producing Inside! Inside! instead of Inside! Outside! .
Additional examples demonstrate how mutable objects like dictionaries are modified in place, reinforcing the distinction between mutable and immutable types.
In summary, the article provides practical code snippets for implementing a counter via closures, highlights pitfalls with immutable types, and clarifies the role of nonlocal in Python's variable scoping.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.