Understanding Python Closures and Decorators
This article explains Python closures and decorators, illustrating how closures capture free variables and how decorators can wrap functions to log calls, handle parameters, and preserve metadata, with clear code examples and step‑by‑step explanations.
Python decorators resemble Java annotations but serve different purposes, enabling aspect‑oriented programming.
To understand decorators, one must first grasp closures, which are functions that capture free variables from their defining environment.
Example closure code:
# print_msg is the outer function
def print_msg():
msg = "I'm closure"
# printer is the nested function
def printer():
print(msg)
return printer
# Obtain the closure
closure = print_msg()
# Output "I'm closure"
closure()The variable msg is local to print_msg, but the nested function retains a reference, forming a closure.
A typical decorator example using functools.wraps prints the function name and arguments.
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('call %s():' % func.__name__)
print('args = {}'.format(*args))
return func(*args, **kwargs)
return wrapperApplying the decorator:
@log
def test(p):
print(test.__name__ + " param: " + p)
test("I'm a param")Output shows the call and arguments.
The @ syntax simply passes the function to the decorator; the same effect can be achieved by calling the decorator explicitly.
When using @functools.wraps(func), the original function’s metadata (name, docstring, etc.) is preserved; removing it changes test.__name__ to wrapper.
Decorators can also accept parameters, requiring three nested functions.
import functools
def log_with_param(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('call %s():' % func.__name__)
print('args = {}'.format(*args))
print('log_param = {}'.format(text))
return func(*args, **kwargs)
return wrapper
return decorator
@log_with_param("param")
def test_with_param(p):
print(test_with_param.__name__)Calling the decorator explicitly yields the same result.
These examples demystify decorators, highlighting Python’s first‑class functions and functional programming features.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
