Python Intermediate Lesson 20
Python Decorators
Wrap functions to add behavior while preserving clean reusable code.
What Is A Decorator?
A decorator is a function that takes another function and returns a new function with extra behavior. Decorators are useful when you want to add the same behavior to many functions without copying code.
def simple_decorator(func):
def wrapper():
print("Before")
func()
print("After")
return wrapper
The wrapper function controls what happens before and after the original function.
Using The @ Syntax
The @decorator_name syntax is a shortcut.
@simple_decorator
def greet():
print("Hello")
This is similar to writing:
greet = simple_decorator(greet)
Now calling greet() actually calls the wrapper returned by the decorator.
Handling Arguments
Most real decorators need to accept arguments for the wrapped function.
def log_call(func):
def wrapper(*args, **kwargs):
print("Calling function")
return func(*args, **kwargs)
return wrapper
*args collects positional arguments, and **kwargs collects keyword arguments.
Preserving Function Metadata
Use functools.wraps so the wrapper keeps the original function’s name and documentation.
from functools import wraps
def log_call(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("Calling function")
return func(*args, **kwargs)
return wrapper
This helps debugging and documentation tools.
When Decorators Help
Decorators are common for logging, timing, access checks, caching, validation, and framework behavior. They are powerful, but they can also make code harder to trace if overused.
Use a decorator when the added behavior is reusable and separate from the main purpose of the function.
Common Mistakes
A common mistake is forgetting to return the wrapper from the decorator. Another is forgetting to return the original function’s result from inside the wrapper.
def wrapper(*args, **kwargs):
func(*args, **kwargs)
If the wrapped function returns a value, this wrapper loses it. Use:
return func(*args, **kwargs)
Quick Summary
- A decorator wraps a function with extra behavior.
@decoratoris shorthand for reassigning the function.- A wrapper usually calls the original function.
- Use
*argsand**kwargsto support flexible arguments. - Use
functools.wrapsto preserve metadata. - Return the wrapped function’s result when needed.
Practice Quiz
Now practice this topic with MCQs and explanations: