Decorators
In Python, decorators are a powerful tool that allows you to modify or extend the behavior of functions or methods without changing their actual code. Essentially, a decorator is a function that takes another function as input and returns a new function that enhances or alters the original one in some way.
Basic Concept of Decorators
A decorator is typically defined as a function that accepts a function (or method) as an argument and returns a new function. The new function can modify the behavior of the original function, such as by adding extra functionality before or after calling the original function.
Basic Syntax:
def decorator_function(original_function):
def wrapper_function():
print("Wrapper executed this before {}".format(original_function.__name__))
return original_function()
return wrapper_functionYou then apply the decorator to a function using the @ syntax:
@decorator_function
def display():
print("Display function executed")
# Running the decorated function
display()Output:
Wrapper executed this before display
Display function executedExplanation:
- The
@decorator_functionsyntax is equivalent to writingdisplay = decorator_function(display). decorator_functionaccepts the original function (display) and returns a new function (wrapper_function), which calls the original function inside it.- This allows the "wrapper" function to execute code before or after the original function call.
Example: Decorators with Arguments
A more advanced example is using decorators that accept arguments:
def decorator_with_args(prefix):
def decorator_function(original_function):
def wrapper_function(*args, **kwargs):
print(f"{prefix}: {original_function.__name__} is being called")
return original_function(*args, **kwargs)
return wrapper_function
return decorator_function
@decorator_with_args("INFO")
def greet(name):
print(f"Hello {name}")
greet("John")Output:
INFO: greet is being called
Hello JohnCommon Use Cases for Decorators:
- Logging: Tracking function calls or errors.
- Authorization: Checking user permissions before executing a function.
- Memoization/Caching: Storing results of expensive function calls.
- Timing: Measuring how long a function takes to execute.
Example: Timing Decorator
import time
def timing_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {end_time - start_time} seconds to execute")
return result
return wrapper
@timing_decorator
def slow_function():
time.sleep(2)
print("Function completed!")
slow_function()Output:
Function completed!
Function slow_function took 2.002347946167469 seconds to executeBuilt-in Decorators
Python provides several built-in decorators, such as:
@staticmethod: Declares a method as a static method.@classmethod: Declares a method as a class method.@property: Converts a method into a read-only property.
Decorators are versatile and can be used to add functionality to your code in a clean, reusable, and readable way.