Blog
Useful Decorators.
Decorators play a vital role in augmenting the functionality of functions and methods without altering their core logic. Diving into three specific decorators designed to track different aspects of function execution, count, time, and caller details. These decorators are useful tools for debugging, optimization, and monitoring in software development.
1. Counting Function Executions with counter
The counter
decorator is designed to keep track of how many times a particular function is executed. This is particularly useful for understanding the usage pattern of a function within an application, aiding in both debugging and performance optimization.
from functools import wraps
def counter(func):
@wraps(func)
def wrapper(*args, **kwargs):
wrapper.count += 1
print(f"\n> Counting execution of '{func.__name__}': {wrapper.count}.")
return func(*args, **kwargs)
wrapper.count = 0
return wrapper
2. Measuring Execution Time with stopwatch
The stopwatch decorator measures the execution time of the decorated function. This information is critical for identifying performance bottlenecks and optimizing slow-running functions to improve the overall efficiency of an application.
from functools import wraps
from timeit import default_timer as timer
def stopwatch(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = timer()
result = func(*args, **kwargs)
print(f"\n> Execution of '{func.__name__}' in: {(timer() - start):.4f} sec.")
return result
return wrapper
3. Inspecting Caller Details with inspect_caller
The inspect_caller decorator provides insights into the caller's context of a function. It prints the file name, function name, and line number from where the decorated function was called. This decorator is invaluable for tracing the flow of execution and debugging complex applications with multiple layers of function calls.
import inspect
from functools import wraps
def inspect_caller(func):
@wraps(func)
def wrapper(*args, **kwargs):
current_frame = inspect.currentframe()
prev_caller_frame = inspect.getouterframes(current_frame, 2)[1]
filename = prev_caller_frame.filename
line_num = prev_caller_frame.lineno
func_name = prev_caller_frame.function
print(f"\n> Function '{func.__name__}' was called from file '{filename}', from function '{func_name}', at line '{line_num}'")
return func(*args, **kwargs)
return wrapper