Decorators in Python
Overview
This lesson covers decorators in Python, a powerful feature that allows you to modify the behavior of functions or methods. Understanding decorators can greatly enhance your ability to write readable, efficient, and elegant Python code.
Introduction
A decorator in Python is a function that takes another function as an argument, adds some kind of functionality or modification to the input function, and returns a modified function. Decorators provide a flexible way to extend the behavior of functions without permanently modifying them.
Basic Concept
- Decorator Syntax: In Python, decorators are applied to functions using the
@
symbol followed by the decorator function name before the function definition.
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
How Decorators Work
- When you decorate a function with
@my_decorator
, you’re essentially saying, “Applymy_decorator
tosay_hello
.” - The
say_hello
function is passed tomy_decorator
as an argument (func
), and thewrapper
function adds behavior before and after callingsay_hello
within it.
Using Decorators
- With Arguments: If the original function takes arguments, the wrapper function must also take those arguments (or use
*args
and**kwargs
to accept an arbitrary number of arguments).
def decorator_with_args(func):
def wrapper(*args, **kwargs):
print("Something before the original function is called.")
result = func(*args, **kwargs)
print("Something after the original function is called.")
return result
return wrapper
Built-in Decorators
- Python includes several built-in decorators, like
@staticmethod
,@classmethod
, and@property
, which are commonly used in object-oriented programming.
Chaining Decorators
- Decorators can be stacked, allowing you to apply multiple modifications to a function.
@decorator_one
@decorator_two
def my_function():
pass
Practical Uses
- Logging: Use decorators to log when a function is called.
- Timing: Measure how long a function takes to execute.
- Authorization: Check if a user has permission to execute a function.
- Caching/Memoization: Store the results of expensive function calls and return the cached result when the same inputs occur again.
Conclusion
Decorators are a significant part of Python’s expressive power, allowing for concise, readable, and efficient code. By mastering decorators, you can write code that is more modular, reusable, and easy to change or extend.
Additional Resources
- Python’s functools.wraps: A helper for decorator-making that preserves the metadata of the original function.
- Real Python - Primer on Python Decorators: Comprehensive guide on decorators with examples.