Closures
A closure is a function object that remembers and has access to variables from its enclosing scope, even after the enclosing scope has finished execution.
def outer_func(x):
def inner_func(y):
return x + y
return inner_funcThis static page keeps the syntax and examples indexed for search, while the coding app handles interactive exploration and saved references.
What it does
Overview
A closure is a function object that remembers and has access to variables from its enclosing scope, even after the enclosing scope has finished execution.
In Python, a closure is created when an inner function (a function defined inside another function) references variables from its outer (enclosing) function's scope, and the outer function returns the inner function. The key characteristic is that the inner function 'remembers' the environment in which it was created, specifically the values of the non-local variables from the outer scope, even if the outer function has already completed its execution. This allows for data encapsulation and the creation of factory functions that generate specialized functions. For example, a `ultiplier(x)` function can return a new function `multiplier(y)` that always multiplies its input `y` by the `x` value captured from `ultiplier`'s scope. Closures are fundamental to implementing decorators and are a powerful concept in functional programming. They enable partial application of functions and can be used to create private state (though not strictly private like in classes). The time complexity of a closure itself is negligible; it's the complexity of the inner function's execution. Best practices include using closures to create functions with pre-configured states, for implementing simple callbacks, or as building blocks for more advanced patterns like decorators, ensuring the captured variables are well-understood and not accidentally modified if unintended.
Quick reference
Syntax
def outer_func(x):
def inner_func(y):
return x + y
return inner_func
See it in practice
Examples
Creating a multiplier function using a closure
def make_multiplier(x):
def multiplier(y):
return x * y
return multiplier
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5))
print(triple(5))10 15
`ultiplier` returns `multiplier`. Each `multiplier` instance (e.g., `double`, `triple`) 'remembers' the `x` value from its creation, even after `ultiplier` has finished.
A simple counter with a closure
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
c1 = make_counter()
c2 = make_counter()
print(c1())
print(c1())
print(c2())1 2 1
Each call to `ounter` creates a new `count` variable. The `nonlocal` keyword is used to modify `count` from the enclosing scope, creating independent counters.
Using closures for event handlers (simplified)
def create_button_handler(button_id):
def handle_click():
print(f"Button {button_id} clicked!")
return handle_click
# Simulate button clicks
button1_click = create_button_handler("Save")
button2_click = create_button_handler("Cancel")
button1_click()
button2_click()Button Save clicked! Button Cancel clicked!
Each `lick` function is a closure that captures its specific `d`, allowing different buttons to have distinct, pre-configured behaviors.
Debug faster
Common Errors
Unintended variable modification
Cause: Forgetting to use `nonlocal` when intending to modify a variable from an enclosing scope, leading to the creation of a new local variable instead.
Fix: If you intend to modify a variable from an outer (non-global) scope within an inner function, explicitly declare it as `nonlocal`.
def outer():
x = 0
def inner():
x = 1 # This creates a new local 'x', doesn't modify outer 'x'
inner()
# print(x) # Still prints 0Runtime support
Compatibility
Source: Python Docs
Common questions
Frequently Asked Questions
A closure is a function object that remembers and has access to variables from its enclosing scope, even after the enclosing scope has finished execution.
Unintended variable modification: If you intend to modify a variable from an outer (non-global) scope within an inner function, explicitly declare it as `nonlocal`.