Decorators in Python are a powerful and flexible tool that allow you to modify the behavior of functions or classes. They are often used to add functionality to existing code in a clean, readable, and reusable way. Decorators can be applied to functions, methods, or classes, and they help in writing concise and maintainable code.
A basic function decorator takes a function as an argument, defines an inner function that adds some behavior, and returns the inner function.
Example:
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
@my_decorator
def say_hello():
print("Hello!")
# Calling the decorated function
say_hello()
Output:
Something is happening before the function is called.
Hello!
Something is happening after the function is called.
In this example, the my_decorator function is used to modify the behavior of the say_hello function.
To create decorators that accept arguments, you need to define a decorator that returns another decorator.
Example:
def repeat(num_times):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
func(*args, **kwargs)
return wrapper
return decorator_repeat
@repeat(num_times=3)
def say_hello():
print("Hello!")
# Calling the decorated function
say_hello()
Output:
Hello!
Hello!
Hello!
In this example, the repeat decorator takes an argument num_times and repeats the execution of the say_hello function the specified number of times.
Class decorators are used to modify or enhance the behavior of classes. A class decorator is similar to a function decorator but operates on a class instead.
Example:
def __init__(self, value):def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class MyClass:
self.value = value
# Creating instances of the class
a = MyClass(10)
b = MyClass(20)
print(a is b) # Output: True
print(a.value) # Output: 10
print(b.value) # Output: 10
In this example, the singleton decorator ensures that only one instance of MyClass is created.