10 simple but super useful Python decorators that do more with less

Decorators are a powerful and flexible feature in Python for modifying or enhancing the behavior of functions or classes. A decorator is essentially a function that takes another function or class as an argument and returns a new function or class. They are often used to add extra functionality or functionality without modifying the original code.

The decorator syntax uses @symbols to apply the decorator to the target function or class. Below we will introduce 10 very simple but useful custom decorators.

Technology Exchange

Technology must learn to share and communicate, and it is not recommended to work behind closed doors. One person can go fast, and a group of people can go farther.

Relevant files and codes have been uploaded, and can be obtained by adding to the communication group. The group has more than 2,000 members. The best way to add notes is: source + interest direction, so that it is convenient to find like-minded friends.

Method ①, add WeChat account: dkl88194, remarks: from CSDN + add group
Method ②, WeChat search official account: Python learning and data mining, background reply: add group

@timer: measure execution time

Optimizing code performance is very important. The @timer decorator helps us track the execution time of a particular function. By wrapping functions with this decorator, I can quickly identify bottlenecks and optimize critical parts of the code. Here's how it works:

 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

Combine @timer with other decorators to comprehensively analyze the performance of your code.

@memoize: cache the result

In data science, we often work with functions that are computationally expensive. The @memoize decorator helped me cache function results, avoiding redundant calculations for the same input, and significantly speeding up my workflow:

 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)

You can also use @memoize in recursive functions to optimize repeated calculations.

@validate_input data validation

Data integrity is critical, and the @validate_input decorator can validate function arguments, ensuring they meet certain criteria before continuing with the computation:

 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

It is convenient to use @validate_input to implement data validation consistently in data science projects.

@log_results: log output

When running complex data analysis, it becomes critical to keep track of the output of each function. The @log_results decorator can help us log the results of a function for easy debugging and monitoring:

 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

Use @log_results in conjunction with the logging library for more advanced logging capabilities.

suppress_errors: graceful error handling

Data science projects often encounter unexpected errors that can disrupt the entire computational pipeline. The @suppress_errors decorator gracefully handles exceptions and continues execution:

 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

@suppress_errors can avoid hiding serious errors, and can also output detailed errors for easy debugging.

Ensuring the quality of data analysis is critical. The @validate_output decorator helps us validate the output of a function, making sure it meets certain criteria before further processing:

 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

This allows to always define well-defined criteria for validation function output.

@retry: retry execution

The @retry decorator helps me retry function execution when an exception is encountered, ensuring greater resilience:

 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

Excessive retries should be avoided when using @retry.

@visualize_results: beautiful visualizations

Automatically generate beautiful visualization results in @visualize_results decorator data analysis

 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

@debug: debugging made easy

Debugging complex code can be time consuming. The @debug decorator can print the function's input parameters and their values ​​for easy debugging:

 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

@deprecated: Handle deprecated functions

As our project iterates, some functions may become obsolete. The @deprecated decorator can notify users when a function is no longer recommended:

 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

Summarize

Decorators are a very powerful and commonly used feature in Python, which can be used in many different situations, such as caching, logging, permission control, etc. By using these Python decorators we introduced in the project, we can simplify our development process or make our code more robust.

Guess you like

Origin blog.csdn.net/qq_34160248/article/details/132664850