Python Decorators is a powerful tool to add functionality to functions or classes without modifying their original code. A decorator is essentially a function that takes another function as an input and adds some functionality to it and then returns the original function with the added behavior.
Let’s look in detail at Python decorators in this article.
What are Python Decorators?
Decorators are a useful tool in Python that helps us to modify the behavior of a class or function. Python decorators are implemented as a function that takes a function as an argument and returns a new function that wraps the original function.
In order to use decorators, we need to place the decorator function above the function or class it modifies and annotate it with the symbol "@" followed by the name of the decorator function.
But before learning decorators, we need to understand some concepts.
What are the functions in Python?
A function is a handy block of code designed to do a specific job you might need to do often. It's like a tool you can use to avoid writing the same code again and again for different situations. Instead of repeating yourself, you put that code inside a function and call the function whenever you need it.
Functions are like building blocks that make your code neat and organized. They help you use the same code in different places without copying and pasting, making your work more efficient.
In Python, there are already available for you to use, and you can also create your own functions to do things your way. This makes your programs more flexible and easier to manage.
First Class Objects
Functions are treated as first-class objects since they can be treated like any other object. This means that functions can be assigned to variables, passed as arguments to other functions, and returned as values from functions.
Treating Functions as Objects
Python
Python
def add(a, b): return a + b
func = add
result = func(2, 3) print(f"The result of the add function is {result}");
Output
Explanation
In the code above, we initialize a function called “add”, assign it to a variable “func” and call the function by passing its arguments.
Passing Functions as Arguments
Python
Python
def apply(func, x, y): return func(x, y)
# Return the sum a and b def add(a, b): return a + b
# Call the 'apply' function with # The 'add' function as an argument result = apply(add, 2, 3) print(f"The result of the add function is {result}")
Output
Explanation
In the code above we initialize a function called 'apply' that takes a function, 'func' and returns the result of calling func with ‘x’ and ‘y’.
Returning a Function from Another Function
Python
Python
# Return the sum of x and y def add(x): def inner(y): return x + y return inner
# Calls the 'add' function a = add(5)
# Calls function 'a' with 'y' # As 3 and assigns the result to `res` res = a(3) print(f"The result of the add function is {res}")
Output
Explanation
In this example, the add() function returns another function called inner(). The inner() function takes an argument y and returns the sum of x.
Inner Functions
A function can be defined within other functions. These are referred to as inner functions or nested functions. These functions are within the scope of another function.
Inner functions have access to the variables of outer functions.
Inner functions allow for encapsulating related functionality within a larger function.
Outer functions do not have access to inner function’s variables.
Python decorators also use inner functions.
Python
Python
def first(): def second(): print("This is the second function.") print("This is the first function.") second()
first()
Output
Explanation
In this example, the outer() function contains an inner function called inner(). First, the outer function is called, and then the inner function is called.
These examples are enough to understand Decorators in Python. Now we will look at the syntax used by Decorators.
Syntax of Python Decorators
Python
Python
def decorator(original): def wrapper(*args, **kwargs): # To execute before the original function is called result = original(*args, **kwargs)
# To execute after the original function is called return result return wrapper
@decorator # Code for the original function def func(): pass
In the above example, “decorator” takes another function, “original” as an argument and returns another function, “wrapper” that adds some functionality before and after the original function. @decorator applies decorator to func, replacing func with a wrapper that includes decorator’s behavior.
Examples of Python Decorator
Now we will look at some of the examples of the Python Decorator function to understand it more clearly.
Decorating Function with Parameters
Here we will look at a python decorator function that multiplies two numbers with a wrapper function that checks for the special case of multiplying by zero.
Python
Python
# Define a decorator function def multiply(original): # Define a function that wraps the original function def wrapper(a, b): print("Let's multiply", a, "and", b, "with decorator") # Check if either a or b is 0 if b == 0 or a == 0: print("The answer is 0") return # Call and return its result return original(a, b) # Return the wrapper function return wrapper
# Define a function that will be # decorated with the multiply function @multiply def multiply_with_decorator(a, b): print("Multiply with decorator: ", a * b)
# No decorator is used def multiply_without_decorator(a, b): print("Multiply without decorator: ", a * b)
# Call the decorated function with some arguments multiply_without_decorator(4, 5) multiply_with_decorator(4, 5)
Output
Explanation
The decorator function checks if the arguments of a decorated function are not zero before calling it. We multiply two numbers and print a message before doing that. First, a function is called without decorator. Finally, the decorated function is called with some arguments to demonstrate the use of the decorator.
Chaining Decorators
This example defines two decorators and applies them in reverse order to a function.
Python
Python
# Define the first decorator function def add_ten(func): def wrapper(x): return func(x) + 10 return wrapper
# Define the second decorator function def multiply(func): def wrapper(x): return func(x) * 20 return wrapper
# Apply the decorators to a function in reverse order @multiply @add_ten def func(x): return x
# Call the decorated function result = func(10) print(f"The result for the function is {result}")
Output
Explanation
We applied two decorators, “add_ten” which adds 10 to the function argument, and “multiply” which multiplies 20 to the function and applies them in reverse order to the function. First, “add_ten” decorator is applied and then the “multiply” decorator.
Here we demonstrate the use of chaining decorators in python.
NOTE: Decorators are normal python functions. Therefore, we can use them in our code as many times as we want.
We define a decorator function in Python using “@decorator” syntax before the function it decorates.
What is the role of decorator in Python?
In Python, the role of the decorator is to modify the behavior of functions or methods. They provide a way to cover functions with additional functionality, helping in tasks like logging, authorization, and code preprocessing. Decorators help keep code concise, reusable, and maintainable.
What is the use of decorator in Python class?
In Python classes, decorators are used to change the behavior of methods. They allow the augmentation of method functionality, like adding authentication checks or logging, without altering the original method code. This enables code reusability and separation of concerns.
Conclusion
In this article, we discussed the Python Decorator Function. You can also read the articlePython Introductionto improve your knowledge of Python.