Fundamentals 7 min read

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.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Understanding Python Closures, Generators, and the nonlocal Keyword with Multiple Implementation Methods

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 1

To 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 5

Method 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 counter

This 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 counter

The 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.

programmingfundamentalsClosureGeneratornonlocal
Python Programming Learning Circle
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.