In Python, a decorator is a special function that modifies or enhances the behavior of another function. Decorators are used to add extra functionality to functions or methods without changing their source code. In this article, we'll discuss how decorators work in Python and provide examples to illustrate their usage.
Basic Syntax
In Python, decorators are implemented as functions that take another function as an argument and return a new function that may modify the input function's behavior. Here's the basic syntax for defining and using a decorator in Python:
def decorator(func):
def wrapper(*args, **kwargs):
# Do something before the function is called
result = func(*args, **kwargs)
# Do something after the function is called
return result
return wrapper
@decorator
def my_function():
# Do something
pass
In this example, we define a decorator function decorator that takes another function func as an argument. The decorator function then defines a new function wrapper that modifies the behavior of the input function by adding extra functionality before and after it is called. Finally, the decorator function returns the modified function wrapper for use elsewhere.
To use the decorator, we simply apply it to the function we want to modify using the @decorator syntax. In this case, we're applying the decorator function to the my_function function.
Practical Examples
Now let's look at some practical examples of decorators in Python.
Timing a Function Call
Suppose we want to time how long it takes to run a particular function. We can create a decorator that prints the time taken to execute the function. Here's how we can do it:
import time
def time_it(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.2f} to run.")
return result
return wrapper @time_it
def my_function():
time.sleep(1)
my_function() # Output: "my_function took 1.00 seconds to run."
In this example, we define a decorator function time_it that takes another function func as an argument. The decorator function then defines a new function wrapper that records the start and end times of the function call, calculates the time taken to execute it, and prints the result. Finally, the decorator function returns the modified function wrapper for use elsewhere.
To use the decorator, we apply it to the my_function function using the @time_it syntax. When we call my_function, the decorator prints the time taken to execute the function.
Logging Function Calls
Suppose we want to log all the calls to a particular function. We can create a decorator that prints a message every time the function is called. Here's how we can do it:
def log_calls(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with args={args} kwargs={kwargs}")
result = func(*args, **kwargs)
print(f"Finished calling {func.__name__}")
return result
return wrapper
@log_calls
def my_function(x, y):
return x + y
my_function(1, 2) # Output: "Callingmy_function with args=(1, 2) kwargs={}" # "Finished calling my_function"
In this example, we define a decorator function log_calls that takes another function func as an argument.
The decorator function then defines a new function wrapper that logs a message before and after the input function is called. Finally, the decorator function returns the modified function wrapper for use elsewhere.
To use the decorator, we apply it to the my_function function using the @log_calls syntax. When we call my_function, the decorator prints a message indicating that the function is being called, and another message indicating that it has finished running.
Conclusion
Decorators are a powerful and flexible feature of Python that allow us to modify the behavior of functions and methods without changing their source code. They're particularly useful for adding extra functionality to existing code, and for implementing cross-cutting concerns such as logging, authentication, and error handling.
In this article, we've covered the basic syntax of decorators in Python and provided examples to illustrate their usage. We hope that this article has helped you understand decorators better and inspired you to start using them in your own code. Happy coding!
Comments