Decorators in Python
Decorators are a powerful and useful tool in Python, allowing you to modify the behavior of a function without changing its code. They are implemented using a special syntax, starting with the @ symbol followed by the name of the decorator function.
To create a decorator, you define a function that takes another function as an argument and returns a modified version of that function.
For example, here is a simple decorator that adds two to the result of a function:
def add_two(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result + 2
return wrapper
To use this decorator, you can apply it to any function by using the @ symbol followed by the name of the decorator:
@add_two
def calculate(x, y):
return x + y
result = calculate(3, 4)
print(result) # prints 9
In this example, the calculate
function is wrapped in the wrapper
function defined in the add_two
decorator. When the calculate
function is called, the wrapper
function is executed instead, which calls the original calculate
function and adds two to its result.
Decorators are often used to add functionality to an existing function without changing its code. For example, you might use a decorator to log the arguments and return value of a function, or to cache the results of a function to improve its performance.
One important thing to note is that decorators are applied in the order in which they appear. For example:
def add_two(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result + 2
return wrapper
def multiply_by_three(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result * 3
return wrapper
@add_two
@multiply_by_three
def calculate(x, y):
return x + y
result = calculate(3, 4)
print(result) # prints 23
In this case, the calculate
function is first decorated with the decorator multiply_by_three
and then with the add_two
decorator. This means that the wrapper
function defined in the multiply_by_three
decorator is applied first, followed by the wrapper
function defined in the add_two
decorator.
Decorators are a powerful tool that can be used to modify the behavior of functions in a concise and elegant way. They are commonly used in Python to add functionality to existing code without changing its implementation.
Decorators can also be useful for modifying the behavior of class methods. For example, you might use a decorator to add a logging feature to all the methods in a class:
def log_methods(cls):
for name, value in vars(cls).items():
if callable(value):
setattr(cls, name, log_method(value))
return cls
def log_method(func):
def wrapper(*args, **kwargs):
print(f"Calling method {func.__name__} with args {args} and kwargs {kwargs}")
result = func(*args, **kwargs)
print(f"Method {func.__name__} returned {result}")
return result
return wrapper
@log_methods
class MyClass:
def method1(self, x):
return x * 2
def method2(self, x, y):
return x + y
obj = MyClass()
obj.method1(10)
obj.method2(5, 6)
Output:
Calling method method1 with args (<__main__.MyClass object at 0x0000024E0439E910>, 10) and kwargs {}
Method method1 returned 20
Calling method method2 with args (<__main__.MyClass object at 0x0000024E0439E910>, 5, 6) and kwargs {}
Method method2 returned 11
In this example, the log_methods
decorator applies the log_method
decorator to all the functions in the class.