Fundamentals 9 min read

Common Python Decorators: Usage, Examples, and Implementation

This article introduces Python decorators, explains their syntax, and provides ten practical examples—including timing, caching, input validation, logging, error suppression, output validation, retry logic, visualization, debugging, and deprecation—complete with code snippets and usage guidance for data‑science and general development tasks.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Common Python Decorators: Usage, Examples, and Implementation

Decorators are a powerful and flexible feature in Python that allow you to modify or enhance the behavior of functions or classes without changing their original code. A decorator is essentially a function that takes another function or class as an argument and returns a new function or class.

The syntax uses the @ symbol placed above the target function or class. Below are ten simple yet useful custom decorators.

@timer: Measure Execution Time

This decorator tracks the execution time of a function, helping identify performance bottlenecks.

<code>import time

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} took {end_time - start_time:.2f} seconds to execute.")
        return result
    return wrapper

@timer
def my_data_processing_function():
    # Your data processing code here
    pass
</code>

@memoize: Cache Results

Useful for expensive functions, this decorator caches results to avoid redundant calculations.

<code>def memoize(func):
    cache = {}
    def wrapper(*args):
        if args in cache:
            return cache[args]
        result = func(*args)
        cache[args] = result
        return result
    return wrapper

@memoize
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)
</code>

@validate_input: Data Validation

Ensures function arguments meet specific criteria before execution.

<code>def validate_input(func):
    def wrapper(*args, **kwargs):
        # Your data validation logic here
        if valid_data:
            return func(*args, **kwargs)
        else:
            raise ValueError("Invalid data. Please check your inputs.")
    return wrapper

@validate_input
def analyze_data(data):
    # Your data analysis code here
    pass
</code>

@log_results: Log Output

Writes function results to a log file for debugging and monitoring.

<code>def log_results(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        with open("results.log", "a") as log_file:
            log_file.write(f"{func.__name__} - Result: {result}\n")
        return result
    return wrapper

@log_results
def calculate_metrics(data):
    # Your metric calculation code here
    pass
</code>

@suppress_errors: Graceful Error Handling

Prevents unexpected errors from crashing the entire workflow by catching exceptions and returning None .

<code>def suppress_errors(func):
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            print(f"Error in {func.__name__}: {e}")
            return None
    return wrapper

@suppress_errors
def preprocess_data(data):
    # Your data preprocessing code here
    pass
</code>

@validate_output: Output Validation

Ensures the function's output conforms to expected standards before further processing.

<code>def validate_output(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        if valid_output(result):
            return result
        else:
            raise ValueError("Invalid output. Please check your function logic.")
    return wrapper

@validate_output
def clean_data(data):
    # Your data cleaning code here
    pass
</code>

@retry: Retry Execution

Retries a function upon encountering exceptions, with configurable attempts and delay.

<code>import time

def retry(max_attempts, delay):
    def decorator(func):
        def wrapper(*args, **kwargs):
            attempts = 0
            while attempts < max_attempts:
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    print(f"Attempt {attempts + 1} failed. Retrying in {delay} seconds.")
                    attempts += 1
                    time.sleep(delay)
            raise Exception("Max retry attempts exceeded.")
        return wrapper
    return decorator

@retry(max_attempts=3, delay=2)
def fetch_data_from_api(api_url):
    # Your API data fetching code here
    pass
</code>

@visualize_results: Automatic Visualization

Generates a visual representation of a function's result using Matplotlib.

<code>import matplotlib.pyplot as plt

def visualize_results(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        plt.figure()
        # Your visualization code here
        plt.show()
        return result
    return wrapper

@visualize_results
def analyze_and_visualize(data):
    # Your combined analysis and visualization code here
    pass
</code>

@debug: Easy Debugging

Prints function name, arguments, and keyword arguments before execution.

<code>def debug(func):
    def wrapper(*args, **kwargs):
        print(f"Debugging {func.__name__} - args: {args}, kwargs: {kwargs}")
        return func(*args, **kwargs)
    return wrapper

@debug
def complex_data_processing(data, threshold=0.5):
    # Your complex data processing code here
    pass
</code>

@deprecated: Mark Obsolete Functions

Issues a warning when a deprecated function is called.

<code>import warnings

def deprecated(func):
    def wrapper(*args, **kwargs):
        warnings.warn(f"{func.__name__} is deprecated and will be removed in future versions.", DeprecationWarning)
        return func(*args, **kwargs)
    return wrapper

@deprecated
def old_data_processing(data):
    # Your old data processing code here
    pass
</code>

In summary, decorators are a versatile Python feature that can be applied to scenarios such as caching, logging, permission control, and more, simplifying development workflows and making code more robust.

performanceCachingvalidationLoggingerror handlingVisualizationDecorators
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.