What it is
Decorators are a way to add extra functionality to your functions without changing the original function’s code. Think of them like a wrapper that adds something extra to a function, without modifying the function itself.
To implement a decorator, you define a function that takes another function as an argument, and returns a new function that adds the desired functionality.
def handle_errors(func):
def wrapper():
try:
func()
except Exception as e:
print(f"Error occurred: {e}")
return wrapper
@handle_errors
def divide():
result = 10 / 0
print(result)I think this example implementation is particularly useful, I’ve used it before to handle errors in functions without having to add try-except blocks everywhere.
You can also go a bit deeper and use decorators with parameters, create class-based decorators for more complex use cases, use built-in decorators like @staticmethod and @classmethod, stack multiple decorators on a single function, or even use functools like functools.wraps to preserve the original function’s metadata when creating decorators.
TIP
Use decorators for cross-cutting concerns like logging, timing, authentication, caching, or error handling. They help keep your core function logic clean and focused.