Python - Decorators
@decorator
syntax in Python? In Python, the @decorator
syntax is used to apply a decorator to a function. Decorators are a way to extend or modify the behavior of functions without changing their actual code. The @decorator
syntax provides a convenient and readable way to specify that a particular function should be wrapped or modified by a decorator function.
Here is the role of the @decorator
syntax:
@decorator_function
def my_function():
# Function code
In this syntax:
-
@decorator_function
: This line indicates that the functionmy_function
should be decorated by thedecorator_function
. -
def my_function():
: This is the definition of the function that will be modified or extended by the decorator.
Here's an example to illustrate the role of the @decorator
syntax:
# Decorator function
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
# Applying the decorator using @decorator syntax
@my_decorator
def say_hello():
print("Hello!")
# Using the decorated function
say_hello()
In this example, @my_decorator
is applied above the say_hello
function definition. This syntax is a shorthand for say_hello = my_decorator(say_hello)
. It indicates that the say_hello
function should be decorated by the my_decorator
function.
When you run this program, you will get the following output:
Something is happening before the function is called. Hello! Something is happening after the function is called.
In Python, higher-order functions are functions that can take other functions as arguments or return functions as results. Decorators leverage the concept of higher-order functions to modify or extend the behavior of functions. A decorator is essentially a higher-order function that takes a function as an argument and returns a new function.
Here's an example to illustrate the concept:
# Higher-order function (decorator)
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
# Function to be decorated
def say_hello():
print("Hello!")
# Applying the decorator using higher-order function
decorated_function = my_decorator(say_hello)
# Using the decorated function
decorated_function()
In this example:
-
my_decorator
is a higher-order function because it takessay_hello
as an argument and returns a new functionwrapper
. -
decorated_function
is the result of applying the decorator tosay_hello
.
When you run this program, you will get the following output:
Something is happening before the function is called. Hello! Something is happening after the function is called.
Now, let's see how decorators and higher-order functions can be used with the @decorator
syntax:
# Decorator function (higher-order function)
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
# Applying the decorator using @decorator syntax
@my_decorator
def say_hello():
print("Hello!")
# Using the decorated function
say_hello()
In this case, @my_decorator
is a shorthand for say_hello = my_decorator(say_hello)
, illustrating how the @decorator
syntax is another way to work with higher-order functions and decorators in Python.
When you run this program, you will get the following output:
Something is happening before the function is called. Hello! Something is happening after the function is called.
In Python, you can create a decorator that takes arguments by defining a higher-order function where the decorator function itself takes parameters. This allows you to customize the behavior of the decorator based on the arguments provided. The syntax involves having a function that returns the actual decorator.
Here's an example of creating a decorator with arguments:
# Decorator function with arguments
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
print(f"Calling {func.__name__}")
result = func(*args, **kwargs)
return result
return wrapper
return decorator
# Applying the decorator with arguments
@repeat(times=3)
def say_hello():
print("Hello!")
# Using the decorated function
say_hello()
In this example:
-
repeat
is a higher-order function that takes an argumenttimes
. -
decorator
is the actual decorator function that takes another functionfunc
as its argument. -
wrapper
is the modified function that repeats the original functiontimes
and prints a message.
When you run this program, you will get the following output:
Calling say_hello Hello! Calling say_hello Hello! Calling say_hello Hello!
You can customize the behavior of the decorator by providing different arguments when applying it to a function. In this example, @repeat(times=3)
indicates that the say_hello
function should be repeated three times.
In Python, you can apply multiple decorators to a single function by stacking them using the @decorator
syntax. When multiple decorators are used, they are applied in the order from the innermost to the outermost, creating a chain of transformations on the original function.
Here's an example to illustrate the use of multiple decorators:
# First decorator
def decorator1(func):
def wrapper():
print("Decorator 1 - Before function is called.")
func()
print("Decorator 1 - After function is called.")
return wrapper
# Second decorator
def decorator2(func):
def wrapper():
print("Decorator 2 - Before function is called.")
func()
print("Decorator 2 - After function is called.")
return wrapper
# Applying multiple decorators
@decorator1
@decorator2
def my_function():
print("Original function.")
# Using the decorated function
my_function()
In this example:
-
decorator1
is the first decorator that adds behavior before and after the function call. -
decorator2
is the second decorator that also adds behavior before and after the function call. -
@decorator1
and@decorator2
are applied tomy_function
in sequence.
When you run this program, you will get the following output:
Decorator 1 - Before function is called. Decorator 2 - Before function is called. Original function. Decorator 2 - After function is called. Decorator 1 - After function is called.
The decorators are applied in the order they are listed, creating a chain of transformations. In this case, decorator1
is the outermost decorator, followed by decorator2
.