Industrial manufacturing
Industrial Internet of Things | Industrial materials | Equipment Maintenance and Repair | Industrial programming |
home  MfgRobots >> Industrial manufacturing >  >> Industrial programming >> Python

Python Closures Explained: How Nested Functions Capture Variables

Python Closures

Discover how Python closures work, how to define them, and why they’re essential for clean, efficient code.

Nonlocal Variables in a Nested Function

Before exploring closures, it’s crucial to understand nested functions and nonlocal variables. A function defined inside another function is called a nested function. Such functions can read variables from their enclosing scope.

In Python, these non‑local variables are read‑only by default. To modify them, you must explicitly declare the variable as nonlocal within the nested function.

Below is a simple example showing a nested function accessing a non‑local variable.

def print_msg(msg):
    # Outer function
    def printer():
        # Nested function
        print(msg)
    printer()

# Execute
print_msg("Hello")

Output

Hello

The nested printer() function can access the msg variable from its outer scope.


Defining a Closure Function

What if the outer function returned the nested function instead of calling it? The code would look like this:

def print_msg(msg):
    def printer():
        print(msg)
    return printer  # Return the nested function

# Store the returned function
another = print_msg("Hello")
another()

Output

Hello

Notice that the function printer still remembers the value of msg even after print_msg has finished executing. This phenomenon—where a function retains access to variables from its defining scope—is called a closure in Python.

To illustrate further, delete the original function and see that the returned function still works:

>>> del print_msg
>>> another()
Hello
>>> print_msg("Hello")
Traceback (most recent call last):
...
NameError: name 'print_msg' is not defined

The returned function continues to function because it captured the necessary data in its closure.


When Do We Have Closures?

In Python, a closure exists when a nested function:


When to Use Closures?

Closures offer several advantages:

Below is a common example: a factory that creates multiplier functions.

def make_multiplier_of(n):
    def multiplier(x):
        return x * n
    return multiplier

# Create specific multipliers
times3 = make_multiplier_of(3)
times5 = make_multiplier_of(5)

print(times3(9))   # 27
print(times5(3))   # 15
print(times5(times3(2)))  # 30

Output

27
15
30

Python’s decorator syntax relies heavily on closures. When you write a decorator, the wrapper function captures the function it decorates, forming a closure.

To inspect a closure, use the __closure__ attribute. It returns a tuple of cell objects that hold the enclosed values. For example:

>>> make_multiplier_of.__closure__
>>> times3.__closure__
(<cell at 0x0000000002D155B8: int object at 0x000000001E39B6E0>,)

Each cell’s cell_contents attribute holds the actual value captured by the closure:

>>> times3.__closure__[0].cell_contents
3
>>> times5.__closure__[0].cell_contents
5

Understanding closures empowers you to write cleaner, more modular Python code that avoids unnecessary globals and embraces functional paradigms.


Python

  1. Master Python Functions: Syntax, Types, and Practical Examples
  2. Mastering Python Function Arguments: Positional, Keyword, and Default Parameters
  3. Mastering Python Recursion: How Functions Call Themselves
  4. Python Lambda Functions: A Practical Guide to Anonymous Functions
  5. Python Generators: Efficient Iteration and Advanced Use Cases
  6. Mastering Python Decorators: Enhance Functions with Expert Techniques
  7. Mastering Python’s strip() Method: Comprehensive Guide & Practical Examples
  8. Python round() Function Explained with Practical Examples
  9. Mastering Python's map() Function: Syntax, Examples, and Best Practices
  10. Python Functions Explained: Building Reusable Code Modules