Syntax
def outer():\n x = value\n def inner():\n return x\n return innerExamples
Basic Closure
An inner function that 'remembers' a variable from its enclosing function.
def make_greeter(greeting):
def greet(name):
return f"{greeting}, {name}!"
return greet
hello_greeter = make_greeter("Hello")
hey_greeter = make_greeter("Hey")
print(hello_greeter("John")) # Hello, John!
print(hey_greeter("Zain")) # Hey, Zain!Closure with Persistent State (Counter)
Using a closure to maintain private state between calls, without using a class.
def make_counter():
count = 0
def increment():
nonlocal count # allows modifying the outer variable
count += 1
return count
return increment
counter = make_counter()
print(counter()) # 1
print(counter()) # 2
print(counter()) # 3
another_counter = make_counter()
print(another_counter()) # 1 (completely independent state)Practical Example: Configurable Validators
Using a closure to build reusable, pre-configured validation functions.
def make_range_validator(minimum, maximum):
def validate(value):
return minimum <= value <= maximum
return validate
is_valid_age = make_range_validator(0, 120)
is_valid_percentage = make_range_validator(0, 100)
print(is_valid_age(25)) # True
print(is_valid_percentage(150)) # FalseBest practices
- Use the 'nonlocal' keyword when an inner function needs to modify (not just read) a variable from its enclosing scope
- Use closures for lightweight cases of remembered state (a counter, a configured function) instead of writing a full class when it fits
- Each call to the outer function creates a fresh, independent closure - variables are not shared between separately created closures
- Prefer a class with __call__ over a closure once the amount of internal state or behavior grows beyond one or two variables
Runtime & versions
Python interpreter. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
Python language reference