Mastering Python Decorators: A Guide to Clean and Efficient Code

Decorators are a cornerstone of advanced Python programming. They provide a powerful way to modify or enhance the behavior of functions and classes without altering their original source code. In this tutorial, we will explore how to build a Performance Monitoring Decorator to measure code execution time efficiently.

Watch the Full Tutorial

1. The Power of "wraps"

A common pitfall when creating decorators is losing the original function's metadata. To prevent this, we use the @wraps decorator from the functools library.

from functools import wraps
from time import perf_counter
from typing import Callable

def get_time(func: Callable) -> Callable:
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = perf_counter()
        result = func(*args, **kwargs)
        end_time = perf_counter()
        
        print(f'Function "{func.__name__}" took {end_time - start_time:.3f}s')
        return result
    return wrapper

2. Implementation & Testing

By using *args and **kwargs, our decorator becomes universal. Let's see it in action with a simulated task:

@get_time
def process_data(data_size: int):
    """Simulates data processing with a delay."""
    import time
    time.sleep(1.5)
    print(f"Processed {data_size} records.")

# Running the decorated function
process_data(5000)
Processed 5000 records.
Function "process_data" took 1.500s

Summary

Using decorators like get_time is a best practice for monitoring performance. It keeps your core logic separated from your utility code, adhering to the Single Responsibility Principle.

Keywords: Python Decorators, Code Optimization, Functools Wraps, Python Performance, Spider Cyber Team.