Implementing Decorators in Your Code
Now that you understand the basics of decorators and their common use cases, let's dive into how to implement them in your own code.
Defining a Simple Decorator
The basic structure of a decorator function is as follows:
def decorator_function(func):
def wrapper(*args, **kwargs):
## Do something before the function is called
result = func(*args, **kwargs)
## Do something after the function is called
return result
return wrapper
The decorator_function
takes a function as an argument, and returns a new function (wrapper
) that wraps the original function. The wrapper
function can perform additional operations before and after the original function is called.
You can then apply the decorator to a function using the @
syntax:
@decorator_function
def my_function(x, y):
return x + y
This is equivalent to:
def my_function(x, y):
return x + y
my_function = decorator_function(my_function)
Passing Arguments to Decorators
Decorators can also accept arguments, which can be useful for configuring the behavior of the decorator. Here's an example:
def repeat_call(n):
def decorator(func):
def wrapper(*args, **kwargs):
result = None
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat_call(3)
def add_numbers(a, b):
return a + b
In this example, the repeat_call
decorator takes an argument n
, which specifies the number of times the decorated function should be called. The repeat_call
function returns a new decorator function that can be applied to other functions.
Decorating Classes
Decorators can also be used to modify the behavior of classes. Here's an example:
def log_class_methods(cls):
for name, method in vars(cls).items():
if callable(method):
setattr(cls, name, log_method(method))
return cls
def log_method(method):
def wrapper(self, *args, **kwargs):
print(f"Calling method {method.__name__}")
result = method(self, *args, **kwargs)
print(f"Method {method.__name__} returned {result}")
return result
return wrapper
@log_class_methods
class MyClass:
def __init__(self, x):
self.x = x
def my_method(self, y):
return self.x + y
In this example, the log_class_methods
decorator is applied to the MyClass
class, and it modifies the behavior of all the methods in the class to log the method calls and their return values.
These are just a few examples of how you can implement decorators in your Python code. Decorators are a powerful and flexible tool, and mastering their use can greatly improve the modularity and maintainability of your code.