In Python, a decorator is a special kind of function that modifies the behavior of another function. Decorators are often implemented as closures, which are nested functions that can remember and access variables from their containing function, even after the containing function has finished executing.
But before diving deep into decorators let us understand some concepts that will come in handy in learning the decorators.
Functions in Python are first-class objects, which means they have the same properties and capabilities as any other object, such as integers or strings. This allows for greater flexibility and power in programming, as functions can be passed as arguments to other functions, returned from other functions, stored in data structures, and used in other ways that are typically reserved for regular objects.
As previously stated, decorators are used to modify the behavior of a function or class. Decorators use functions as arguments in another function, which is then called inside the wrapper function.
A decorator is applied to a function using the @decorator_name
notation, which is a shorthand for calling decorator_name(function)
and assigning the result back to the function.
Here is an example of a decorator function that adds logging to a function:
import logging
def log_decorator(func):
def wrapper(*args, **kwargs):
logging.info(f"Calling function {func.__name__} with args: {args}, kwargs: {kwargs}")
result = func(*args, **kwargs)
logging.info(f"Function {func.__name__} returned: {result}")
return result
return wrapper
@log_decorator
def add(x, y):
return x + y
add(1, 2)
</code>
In this example, the log_decorator function takes a function as an argument and returns a wrapper function that logs the function call and its result. The @log_decorator syntax is used to apply the decorator to the add() function. When the add(1, 2) is called, it will first log the function call, execute the original add function and then log the result.
When the code runs, it will output something like this:
INFO:root:Calling function add with args: (1, 2), kwargs: {}
INFO:root:Function add returned: 3
This is a simple example, but decorators can be used in many ways to add functionality to functions and classes in a clean, reusable way.
We can chain multiple decorators together to apply multiple modifications to a function. Here’s an example:
import time
def timer_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Time taken: {end_time - start_time}")
return result
return wrapper
def log_decorator(func):
def wrapper(*args, **kwargs):
logging.info(f"Calling function {func.__name__} with args: {args}, kwargs: {kwargs}")
result = func(*args, **kwargs)
logging.info(f"Function {func.__name__} returned: {result}")
return result
return wrapper
@timer_decorator
@log_decorator
def add(x, y):
return x + y
add(1, 2)
In this example, both timer_decorator and log_decorator are applied to the add() function using the @ syntax. So, when the add(1, 2) is called, it will first log the function call, then it will execute the original add function, measure the execution time and then log the result.
The order of decorators is important, as it determines the order in which the decorators’ wrapper functions are executed. In this example, log_decorator is applied first and timer_decorator is applied second, so logging happens before timing. If you want to change the order, you can swap the decorators like this:
@log_decorator
@timer_decorator
def add(x, y):
return x + y
This way, the timing will happen before the logging.
Note: also read about Python Closures
Please follow me to read my latest post on programming and technology if you like my post.
https://www.instagram.com/coderz.py/
https://www.facebook.com/coderz.py
Staying up to the mark is what defines me. Hi all! I’m Rabecca Fatima a keen learner, great enthusiast, ready to take new challenges as stepping stones towards flying colors.
Problem Statement: Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. Example…
Given an integer A. Compute and return the square root of A. If A is…
Given a zero-based permutation nums (0-indexed), build an array ans of the same length where…
A heap is a specialized tree-based data structure that satisfies the heap property. It is…
What is the Lowest Common Ancestor? In a tree, the lowest common ancestor (LCA) of…