Of course! Let's break down funcclosure (more commonly just called a closure) in Python. It's a powerful and elegant feature that every Python developer should understand.

What is a Closure? (The Simple Definition)
A closure is a function object that remembers values from the environment in which it was created, even if that environment is no longer active.
Let's break that down:
- Function Object: In Python, functions are "first-class citizens," meaning you can treat them like any other variable (pass them as arguments, return them from other functions, etc.).
- Remembers values from its creation environment: This is the key part. A closure "captures" local variables from the outer function where it was defined.
The Three Conditions for a Closure
For a closure to be created, three conditions must be met:
- There must be a nested function (a function defined inside another function).
- The nested function must reference a variable from the outer function's scope.
- The outer function must return the nested function.
If all three are true, you have a closure.

A Concrete Example
Let's build a closure step-by-step.
Example: A Simple Multiplier
Imagine you want to create specialized multiplication functions. Instead of writing multiply_by_2(x), multiply_by_3(x), etc., you can create a "factory" function that creates these specialized functions for you.
def make_multiplier(n):
"""This is the outer function."""
print(f"Creating a multiplier for {n}")
def multiplier(x):
"""This is the nested function."""
# This is the crucial part: it 'captures' the variable 'n'
# from the outer function's scope.
return x * n
# The outer function returns the nested function object.
return multiplier
# --- Let's use it ---
# Create a function that multiplies by 3
multiply_by_3 = make_multiplier(3)
# Create a function that multiplies by 5
multiply_by_5 = make_multiplier(5)
# Now, let's use these new functions
print(f"5 * 3 = {multiply_by_3(5)}")
print(f"10 * 5 = {multiply_by_5(10)}")
# Let's inspect the functions to see the closure
print(f"Type of multiply_by_3: {type(multiply_by_3)}")
print(f"__closure__ of multiply_by_3: {multiply_by_3.__closure__}")
Output:
Creating a multiplier for 3
Creating a multiplier for 5
5 * 3 = 15
10 * 5 = 50
Type of multiply_by_3: <class 'function'>
__closure__ of multiply_by_3: (<cell at 0x...: int object at 0x...>,)
What's Happening Here?
-
make_multiplier(3)is called.
(图片来源网络,侵删)- The variable
nis set to3. - The
multiplierfunction is defined insidemake_multiplier. It knows aboutn. make_multiplierreturns themultiplierfunction object. Let's call this returned objectmultiply_by_3.
- The variable
-
The
make_multiplierfunction finishes and its local scope is destroyed. Normally, the variablenwould be gone. But becausemultiply_by_3is a closure, it holds a reference to thatnvalue. -
multiply_by_3(5)is called.- Even though
make_multiplieris long gone, themultiply_by_3function still has access to thenit captured (which is3). - It calculates
5 * 3and returns15.
- Even though
The __closure__ attribute confirms this. It shows a "cell" object containing the value of n that was captured. This is the mechanism that keeps the variable "alive" after the outer function has finished.
Practical Use Cases for Closures
Closures aren't just a theoretical concept. They are used all the time, often without you even realizing it.
Use Case 1: Function Factories (as shown above)
This is the most common pattern. You create a function that generates other functions with pre-configured behavior.
def make_greeter(greeting):
def greeter(name):
return f"{greeting}, {name}!"
return greener
say_hello = make_greeter("Hello")
say_goodbye = make_greeter("Goodbye")
print(say_hello("Alice")) # Output: Hello, Alice!
print(say_goodbye("Bob")) # Output: Goodbye, Bob!
Use Case 2: Data Hiding / Encapsulation
Closures can be used to create private-like state. You can't access the "private" variable directly from the outside, but the inner functions can.
def counter_generator():
count = 0 # This is a "private" variable
def increment():
nonlocal count # Needed to modify a non-local variable
count += 1
return count
def get_count():
return count
return increment, get_count
# We get two functions back
increment, get_count = counter_generator()
print(increment()) # Output: 1
print(increment()) # Output: 2
print(increment()) # Output: 3
print(get_count()) # Output: 3
# You cannot directly access or modify 'count'
# This would raise an error:
# print(count) # NameError: name 'count' is not defined
This pattern is a simple way to achieve what other languages do with classes and private members.
Use Case 3: Decorators
Decorators are a core feature in Python, and they are fundamentally built on closures. A decorator is a function that takes another function as an argument and extends its behavior without explicitly modifying it.
import time
def timing_decorator(func):
"""This is the outer function (the decorator)."""
def wrapper(*args, **kwargs):
"""This is the inner function (the closure)."""
start_time = time.time()
result = func(*args, **kwargs) # Call the original function
end_time = time.time()
print(f"'{func.__name__}' took {end_time - start_time:.4f} seconds to run.")
return result
return wrapper
@timing_decorator
def slow_function():
time.sleep(1)
# When you call slow_function(), you are actually calling the wrapper()
slow_function()
Output:
'slow_function' took 1.0021 seconds to run.
Here, timing_decorator returns the wrapper function, which has "closed over" the func variable. This allows wrapper to call the original function and add timing logic around it.
Closures vs. Lambdas
You can often achieve the same result with a lambda function. Lambdas are just a more concise way to write simple, anonymous functions.
Let's rewrite our first multiplier example using a lambda:
def make_multiplier_lambda(n):
return lambda x: x * n
multiply_by_7 = make_multiplier_lambda(7)
print(multiply_by_7(10)) # Output: 70
This works perfectly and is very clean. However, for more complex logic (multiple lines, statements, etc.), a standard def function is more readable and powerful. Closures created with def are often easier to debug and understand because they have a name and can have docstrings.
Summary
| Feature | Description |
|---|---|
| What it is | A function that remembers variables from its enclosing scope. |
| How it's made | A nested function that references a non-local variable, and the outer function returns it. |
| Key Mechanism | The __closure__ attribute, which holds references to the captured variables. |
| Why use it? | To create function factories, hide state (encapsulation), and build powerful decorators. |
| Pythonic Use | It's a fundamental building block for many advanced Python patterns. |
