In Python, Decorators are models of software design. They dynamically modify the functionality of a function, method, or class without having to directly use subclasses or modify the source code of the decorated function.
If used correctly, then these functions can become powerful tools in the development process. This article covers the implementation and applications of decorators in Python.
Also, Read – Machine Learning Full Course for free.
Decorators Functions
Decorators augment the behaviour of other functions or methods. Any function that takes another function as a parameter and then returns an augmented function then it can be used as a decorator.
def super_secret_function(f):
return f
@super_secret_function
def my_function():
print("This is My Secret Function")
Code language: PHP (php)
The @ -notation is a syntactic sugar equivalent to the following:
my_function = super_secret_function(my_function)
This is important to keep in mind to understand how decorators work. This “sugarless” syntax clearly explains why the decorator function takes a function as an argument and why it must return another function. It also shows what would happen if you didn’t return a function:
def disabled(f):
pass
@disabled
def my_function():
print("This is my function")
my_function()
#TypeError: 'NoneType' object is callable
Code language: CSS (css)
So, we usually define a new function inside the decorator and return it. This new function would first do something it needs, then call the original function, and finally process the return value. Consider this simple decorator function that prints out the arguments that the original function receives and then calls it.
#This is Decorator
def print_args(func):
def inner_func(*args, **kwargs):
print(args)
print(kwargs)
return func(*args, *kwargs)
return inner_func
@print_args
def multiply(num_a, num_b):
return num_a * num_b
print(multiply(3, 5))
Code language: PHP (php)
Output:
(3,5) – This is actually the ‘args’ that the function receives.
{} – This is the ‘kwargs’, empty because we didn’t specify keyword arguments.
15 – The result of the function.
Decorators in Action: Creating a Singleton Class
A singleton is a pattern that limits the instantiation of a class to an instance/object. Using a decorator, we can define a class as a singleton by forcing the class to return an existing instance of the class or create a new instance (if it doesn’t exist).
def singleton(cls):
instance = [None]
def wrapper(*args, **kwargs):
if instance[0] is None:
instance[0] = cls(*args, **kwargs)
return instance[0]
return wrapper
Code language: JavaScript (javascript)
This decorator can be added to any class declaration and will ensure that at most one instance of the class is created. Any subsequent invocation will return the already existing class instance.
@singleton
class SomeSingletonClass:
x = 2
def __init__(self):
print("created")
instance = SomeSingletonClass() #prints "created"
instance = SomeSingletonClass() # doesn't prints anything
print(instance.x) #2
instance.x = 3
print(SomeSingletonClass().x) #3
Code language: Python (python)
So it doesn’t matter if you refer to the class instance through your local variable or create another “instance”, you always get the same object. I hope you liked this article on Decorators in Python. Feel free to ask your valuable questions in the comments section below.
Also, Read – Build TikTok Algorithm with Machine Learning.