January 23, 2025

How and when to use “decorators” in Python

Spread the love

Things to remember before understanding decorators

  • Functions in python are just like any other objects, that means:
    • It can be passed around
    • Called within another function
    • Can be returned from another function

Decorator

A decorator wraps a function and allows you to put other functional codes around it. In other words, it lets you change the functionality of any function and modify (decorate) it to your need.

Here is an example:
We updated the lets_party function to be executed only in a certain time frame.

# Importing datetime
from datetime import datetime

# Defining the decorator function
def my_decorator(func):
    def wrapper():
        if 16 <= datetime.now().hour < 22:
            func()
        else:
            pass
    return wrapper

# Defining our function
def lets_party():
    print('Party is ON!')

# Decorating my function with the decorator
wanna_party = my_decorator(lets_party)

# Calling the decorated function
wanna_party()

Some explanation:

  • We defined the function lets_party, which prints ‘Party is ON!’ every single time.
  • We then defined our my_decorator function, inside which we define a wrapper function which has a condition, which is that if the current hour is between 16 and 22 then execute the function passed to my_decorator. Then we return the wrapper function.
  • We later call our decorator function which lets_party function as an attribute and asign it to wanna_party. That means, wanna_party now is pointing to the wrapper function which has a certain condition.
  • So now when we call wanna_party, it will print ‘Party is ON!’ depending on the provided condition.

The key concept here is that we are passing a function within another function and we are also wrapping that function with another function.
Don’t worry about the syntax, I wrote the code this way so that it’s easier to understand what’s happening behind the scene. We will now look at a better way to write our decorators.


Pythonic way of writing a decorator

@my_decorator
def let_party():
    print('Party is ON!')

And to call that function you can simply call it by saying: lets_party()


Decorating functions with arguments and returning value

Let’s say we have a simple divide function that returns the division of two numbers

def divide(a, b):
    return a/b

If we use the above function with “0” as the second argument, the function will throw a ZeroDivisionError. Currently, the function isn’t equipped to handle that. Let’s change that and decorate our function with some additional functionalities.
NOTE: Our “divide” function here takes in argument as well as returns something

# Defining our decorator
def smart_divide(func):
    def wrapper(a, b):
        print(f'I am dividing {a} by {b}')
        if b == 0:
            print('Ooops! cannot divide by 0')
            return  # Returns None
        # We need to return the func back since our original function is expecting something to be returned
        return func(a, b)
    return wrapper

@smart_divide
def divide(a, b):
    return (a/b)

solution_1 = divide(4,2)
print(solution_1)

solution_2 = divide(2, 0)
print(solution_2)

And here’s the output

# Output for solution_1
I am dividing 4 by 2
2.0

# Output for solution_2
I am dividing 2 by 0
Ooops! cannot divide by 0
None

In this manner, we can decorate a function that takes parameters and is returning something as well.


Decorators that work with any number of parameters

If you noticed, the wrapper function in the above example takes the same number of parameters as our main function. We could modify the decorator function to work with any number of parameters (given that our main function supports it).

def works_for_all(func):
    def wrapper(*args, **kwargs):
        print('I can decorate any function!')
        return func(*args, **kwargs)
    return wrapper

Hopefully, now you know when and how to use decorators in python.


Spread the love

One thought on “How and when to use “decorators” in Python

  1. I have recently started a website, the info you provide on this website has helped me tremendously. Thank you for all of your time & work. “There can be no real freedom without the freedom to fail.” by Erich Fromm.

Leave a Reply

Your email address will not be published. Required fields are marked *