A decorator design pattern in Python is a way of adding new functionality to an existing function or class without modifying its original structure. It is also known as a wrapper, because it wraps the original function or class with another function or class that provides the extra functionality. Decorators are commonly used to implement cross-cutting concerns, such as logging, caching, authentication, etc.
In Python, decorators are implemented using the @ symbol, which is placed before the definition of the function or class that needs to be decorated. For example, suppose we have a function that prints a message:
def hello():
print("Hello, Corgi!")
We can create a decorator function that adds a timestamp to the message:
import datetime
def add_timestamp(func):
# define a wrapper function that calls the original function and adds the timestamp
def wrapper():
print(datetime.datetime.now())
func()
# return the wrapper function
return wrapper
We can then apply the decorator to the hello function using the @ symbol:
@add_timestamp
def hello():
print("Hello, Corgi!")
Now, when we call the hello function, it will also print the current date and time:
hello()
# 2023-10-06 16:23:45.789
# Hello, Corgi!
We can also use classes as decorators in Python, by implementing the call () method, which allows an object to behave like a function. For example, suppose we have a class that counts how many times a function is called:
class Counter:
# initialize the counter attribute to zero
def __init__(self):
self.count = 0
# define the __call__ method that takes a function as an argument and returns a modified version of it
def __call__(self, func):
# define a wrapper function that increments the counter and calls the original function
def wrapper():
self.count += 1
print(f"This function has been called {self.count} times")
func()
# return the wrapper function
return wrapper
We can then apply the class as a decorator to the hello function using the @ symbol:
@Counter()
def hello():
print("Hello, Corgi!")
Now, when we call the hello function, it will also print how many times it has been called:
hello()
# This function has been called 1 times
# Hello, Corgi!
hello()
# This function has been called 2 times
# Hello, Corgi!
Decorators can be used to add a wide variety of functionality to existing objects. For example, you can use decorators to:
- Add logging to functions.
- Add caching to functions.
- Validate user input.
- Add authorization to functions.
Decorators are a powerful tool that can be used to make your Python code more efficient, reusable, and secure.
Here are some examples of how decorators can be used in Python:
- Decorate a function to log its execution time.
- Decorate a function to cache its results.
- Decorate a function to validate its arguments.
- Decorate a function to require authorization to access it.
- Decorate a class to add new methods to it.
If you want to learn more about decorator design pattern in Python, you can check out these sources: