Hello Developers, In this article, You will learn all about the most important Python topic called decorator in Python. Decorators in Python are the most famous and important because they provide the functionality to change the functionality or behavior of the existing Python code without altering the actual code.
Sometimes we have a function and we want to increase their functionality without a coding change in that function, So in that scenario decorator comes into the picture because the use of a decorator can increase the functionality of the existing function without altering the code.
For FYI, a Function in Python is a first-class object, Which means the functions in Python can be assigned to a variable or can be returned by another function, passed as a parameter to a function, or defined into another function.
That’s why it is very important to know some interesting facts about Python functions before going through decorators in Python.
Let’s start.
Headings of Contents
Assign function to the variable
Being a first-class object, Python functions can be assigned to the variable, and that variable can be used as a function.
Let’s see how can I do that.
Examples:
def Addition(x, y): print(f"Addition of {x} and {y} is:- {x + y}") # Without assigning a function to the variable. Addition(12, 34) # Assign a function to the variable. x = Addition x(12, 30)
Output
The addition of 12 and 34 is:- 46
The addition of 12 and 30 is:- 42
Defining a function inside another function
Python function can be defined into another Python function. As you can see in the below example, How I have defined the sum() function inside the Addition() function.
Example:
def Addition(a, b): def sum(): return f"Addition of {a} and {b} is:- {a + b}" return sum result = Addition(20, 30) print(result())
Output
The addition of 20 and 30 is:- 50
Passing function as an argument to the function
As we know first is a first-class object in Python that can be passed as an argument to another function.
Example:
def Message(msg): return msg() def welcome(): print("Welcome to the programming funda") Message(welcome)
Output
Welcome to the programming funda
Now, after learning all the above concepts we are ready to learn about Python decorators.
What are Decorators in Python?
Decorators in Python are a powerful tool that allows Python programmers to change the behavior of the existing Python function or class without changing the function and class’s actual code. May you be confused with this definition but wait, After this tutorial, you will completely get rid of this confusion.
The decorator takes a function as an argument adds some functionality and returns it.
In Python, decorators are implemented as functions (or classes) that take another function as an argument and return a new function that enhances or alters the original one. This approach adheres to the principle of separation of concerns and can make code more modular, reusable, and readable.
Why Decoartos are Useful Python
There are several reasons for decorators to be useful in Python some of them are listed below as you can see.
- Code Reusability: Decorators promote code reusability by allowing you to apply the same enhancement logic to multiple functions without duplicating code.
- Separation of Concerns: They help separate the core functionality of a function from the additional features or behaviors, making your code cleaner and more maintainable.
- Enhanced Functionality: Decorators can add, modify, or extend the behavior of functions or methods dynamically. This can be useful for logging, access control, instrumentation, caching, and more.
- Cleaner Code: By using decorators, you can keep your main logic cleaner and more focused on its core responsibilities, while the decorators handle the auxiliary tasks.
Now Let’s understand the Python decorators by examples.
Python Decorators Examples
Now let’s see some Python decoratos examples and explanations so that you can get more clarity about the decoratos in Python.
Example:
def smart(any_function): def inner(): print("Before execution") any_function() print("After execution") return inner def func2(): print("Inside the function") var = smart(func2) var()
Output
Before execution Inside the function After execution
Let’s break down the code to get more insights.
- Defining the decoration called ‘smart‘: The ‘smart’ is a decorator function that takes a function ‘any_function‘ as an argument and inside the ‘smart‘ function there is another function defined called ‘inner‘.
- smart(any_function):- It accepts a function
any_function
and defines a nested functioninner
. - inner() function:
- This is the function that will be returned by the
smart
decorator. - It prints
"Before execution"
, then callsany_function()
, and finally prints the"After execution"
message.
- This is the function that will be returned by the
- return inner:- The
inner
function is returned from thesmart
function which means it is replacing the original function (func2) with inner.
- smart(any_function):- It accepts a function
- Defining
func2
function:- The func2 is just a normal function that prints a simple message ‘Inner function‘. - Applying the Decorator:- Using
var = smart(func2)
to apply the decorator.- Here,
smart(func2)
is called. This applies thesmart
decorator tofunc2
, and it returns theinner
function withfunc2
bound asany_function
. var
now holds a reference to theinner
function.
- Here,
- Calling the Decorated Function: Using
var()
to call the decorated function. - After calling the var(), the above sequence will be triggered and the following output will be generated.
Before execution Inside the function After execution
Python provides another way to use the decorator using @decoratorname.Instead of assigning decorator to a variable just use the @decoratorname with the function on which you want to apply decorator.
Let’s see
Example:
def smart(any_function): def inner(): print("Before execution") any_function() print("After execution") return inner @smart def func2(): print("Inside the function") func2()
Output
Before execution
Inside the function
After execution
Here, I have created a function decorator ‘upper_case‘ that is capable of converting the string to upper case.
Example:
def upper_case(myfunc): result = myfunc() print(result.upper()) @upper_case def message(): return "Welcome to Programming Funda Python tutorial."
Output
WELCOME TO PROGRAMMING FUNDA PYTHON TUTORIAL.
A function return value
In all the above examples, The inner or nested function inside the function decorator is not returning any value but here we will see what will happen if a nested function returns some value.
def smart(any_function): def inner(*args, **kwargs): print("Before execution") return_value = any_function(*args) print("After execution") return return_value return inner @smart def func2(a, b): print("Inside the function") return a + b print(f"Sum :- {func2(12, 23)}")
When you run the above program you will get output like this:
Before execution
Inside the function
After execution
Sum:- 35
Break down of the above example:
- smart(any_function): The ‘smart’ is a function decorator that takes a function as an argument.
- def inner(*args, **kwargs):- The ‘inner’ is a nested function or an inner function that takes any number of positional arguments (*args) and keyword arguments (**kwargs).
- print a message ‘Before execution‘ before calling the original function.
- Call the original function (any_function) with provided arguments and capture the output value in a variable return_value.
- print a message ‘After execution‘ after calling the original function.
- return the value stored inside the return_value variable.
- Decorating the original function (func2) with @smart.
- Apply the smart decorator to the func2 function by using @smart and the func2 function is replaced by the inner function returned by the smart. Actually @smart is the shorthand for func2 = smart(func2).
- func2(a, b): The original function
func2
takes two arguments, prints a message, and returns their sum.
- Calling the Decorated Function
- func2(12, 23): When func2 is called, The inner function will get executed behind the scenes because of the decorator.
This is the way you can use decorators in Python.
Let’s understand some real-life application use cases of Python decoratos.
Use Cases of Decorators in Real-Life Applications
These are some major uses of Python decorators in real-life Python applications.
- Authorization: Decorators can enforce access control in web applications by checking user permissions before allowing function execution.
def requires_admin(func): def wrapper(user, *args, **kwargs): if not user: return func(user, *args, **kwargs) else: raise PermissionError("User must be an admin") return wrapper @requires_admin def allow_login(user): # code to perform login return "Admin has been logged in" # User can be normal user or admin, It True then or normal user otherwise it will admin user = True print(allow_login(user))
- Timing: Decorators can measure the time taken by a function to execute, which can be useful for performance profiling.
import time def calculuate_execution_time(func): def wrapper(user, *args, **kwargs): if user: start_time = time.time() func(user, *args, **kwargs) end_time = time.time() print(f"Function {func.__name__} took {end_time - start_time:.4f} seconds to execute") else: raise KeyError("User not found") return wrapper @calculuate_execution_time def delete_user(user): # code to perform user delete operations suppose it takes 3 seconds time.sleep(3) # User can be normal user or admin, It True then or normal user otherwise it will admin user = True delete_user(user)
- Validation: Decorators can validate input data before a function executes, ensuring that functions are called with valid arguments.
def validate_positive(func): def wrapper(x, *args, **kwargs): if x <= 0: raise ValueError("Input must be positive") return func(x, *args, **kwargs) return wrapper @validate_positive def square_root(x): import math return math.sqrt(x) print(square_root(16)) # Valid
Note:- 👉 Explore Python class decoratos.
Conclusion
So In this article, you have learned all about Decorators in Python along with examples and real-life use cases of the Python decoratos. Decorators in Python play the most major role when you want to change the behavior of the existing Python code without altering that actual code.
As A Python programmer, must use the decorators when we want to perform some operations in a function without changing the actual code of the function and we want to perform the same operations in multiple functions because decorators are the concepts of reusability.
A single decoratos can be applied to multiple functions if required.
If this article genuinely helps you, please share and keep visiting for further Python tutorials.
For more information:- Click Here
Happy Learning.