How to Master the decorator pattern in Python: A simple way to learn a design pattern

python decorator design pattern

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:

https://www.programiz.com/python-programming/decorator

Related posts

Leave a Comment