Yandex

Python Closures



Understanding Python Closures

In Python, closures are a powerful and often misunderstood concept. If you've ever wondered how a function can remember the environment in which it was created—even after that environment is gone—then you're ready to dive into closures.

What is a Closure in Python?

A closure is a nested function that captures the state of its enclosing scope—even if that scope has finished execution. This allows the inner function to remember variables from the outer function.

Why Do Closures Matter?

Closures allow you to:

  • Preserve data across function calls without using global variables
  • Write more concise and elegant code
  • Implement decorators and function factories

How to Create a Closure

Let’s break it down with an example. The closure is formed when three conditions are met:

  1. There is a nested function
  2. The nested function references variables from the outer function
  3. The outer function returns the nested function
def outer_function(msg):
    def inner_function():
        print(f"Message: {msg}")
    return inner_function

# Create the closure
my_closure = outer_function("Hello Closure!")

# Now call the closure
my_closure()
Message: Hello Closure!

What Just Happened?

Even though outer_function has already finished executing, the variable msg still exists in memory. That's because inner_function has "closed over" the variable msg.

Checking for Closure

We can actually inspect the closure using the __closure__ attribute.

print(my_closure.__closure__)
print(my_closure.__closure__[0].cell_contents)
(<cell at 0x...: str object at 0x...>,)
Hello Closure!

This confirms that msg is stored as part of the closure environment.

Real-World Use Case: Counter Generator

Closures shine when used to create functions that remember state. Here’s a classic counter example:

def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

# Create a counter function
counter1 = make_counter()

print(counter1())
print(counter1())
print(counter1())
1
2
3

The variable count is preserved between function calls thanks to the closure.

Common Pitfalls and Checks

  • Don’t expect the outer function's variables to persist unless they are referenced in the inner function.
  • Use nonlocal to modify enclosed variables. Without it, Python treats them as read-only.
  • A closure is not created if the inner function doesn’t reference outer variables.
def no_closure():
    x = 5
    def show():
        print("Hello")
    return show

fn = no_closure()
print(fn.__closure__)  # Will print None
None

Closures vs. Lambda Functions

Closures can also be created using lambda expressions, which is common in factory functions or decorators.

def multiplier(factor):
    return lambda x: x * factor

double = multiplier(2)
print(double(5))  # 10
10

Recap: When to Use Closures

Closures are useful when:

  • You want to keep some data private (function-level encapsulation)
  • You need a factory function that generates other functions with customized behavior
  • You’re building decorators or callback systems

Summary

Closures are not just a technical trick—they allow for cleaner, more modular, and more reusable code. By remembering the context in which they were created, closures enable inner functions to maintain state across multiple invocations, even after their outer function is long gone.

Next Steps

Now that you understand closures, try writing one that returns a custom logger or message formatter. Experiment with modifying state, returning different outputs, or wrapping other functions!



Welcome to ProgramGuru

Sign up to start your journey with us

Support ProgramGuru.org

You can support this website with a contribution of your choice.

When making a contribution, mention your name, and programguru.org in the message. Your name shall be displayed in the sponsors list.

PayPal

UPI

PhonePe QR

MALLIKARJUNA M