How to Create a Counter Closure in Python

Build a closure in Python that remembers and increments a counter across calls without using global variables.

Medium Python 3.0+ Aug 9, 2026 Functions & basics 13 views 0 copies

Python code

13 lines
Python 3.0+
def create_counter(start=0):
    count = start
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

if __name__ == "__main__":
    counter = create_counter(10)
    print(counter())
    print(counter())
    print(counter())

Output

stdout
11
12
13

How it works

This example uses a closure — an inner function that captures variables from its enclosing scope. The nonlocal keyword inside increment tells Python that count refers to the variable in create_counter, not a new local one. Each call to increment looks up and modifies that same count, so the state persists between calls. Since the inner function holds a reference to its closure environment, the counter retains its value even after create_counter finishes executing.

Common mistakes

  • Forgetting `nonlocal`, which causes a `UnboundLocalError` when assigning to `count`
  • Using `global` instead of `nonlocal`, which would only work for module-level variables
  • Returning `count` before incrementing, so the first call returns the initial value instead of start+1

Variations

  1. Use a mutable default argument like `def increment(count=[start])` for older Python versions without `nonlocal`
  2. Implement the same counter as a class with a `__call__` method for an object-oriented alternative

Real-world use cases

  • Generate sequential IDs for logging or tracing events in a multi-request web application.
  • Track retry attempts for a network call within a single function invocation.
  • Create per-user request counters in an API middleware without global mutable state.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Functions & basics

Related tutorials and quizzes for this topic.