Python中十个常用的自定义装饰器的使用详解

Written by

in

文章目录
  • 优化代码性能时,了解函数的执行时间至关重要。@timer 装饰器可以轻松跟踪函数的运行时长: 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__} 执行耗时: {end_time – start_time:.2f} 秒”) return result return wrapper @timer def process_large_dataset(): “””模拟处理大型数据集””” data = [x ** 2 for x in range(1000000)] return sum(data) # 使用示例 result = process_large_dataset() print(f”处理结果: {result}”)
  • 对于计算成本高的函数,@memoize 可以缓存结果,避免相同输入的重复计算: def memoize(func): cache = {} def wrapper(*args): if args in cache: print(f”从缓存中获取结果: {args} -> {cache[args]}”) return cache[args] result = func(*args) cache[args] = result print(f”计算并缓存结果: {args} -> {result}”) return result return wrapper @memoize def fibonacci(n): if n <= 1: return n return fibonacci(n – 1) + fibonacci(n – 2) # 使用示例 print(fibonacci(10)) # 第一次计算 print(fibonacci(10)) # 从缓存获取
  • 确保函数接收到的参数符合预期标准: def validate_input(*expected_types): def decorator(func): def wrapper(*args, **kwargs): for i, (arg, expected_type) in enumerate(zip(args, expected_types)): if not isinstance(arg, expected_type): raise TypeError(f”参数 {i} 应该是 {expected_type} 类型,但得到的是 {type(arg)}”) return func(*args, **kwargs) return wrapper return decorator @validate_input(list, int) def get_list_slice(data, n): “””获取列表的前n个元素””” return data[:n] # 使用示例 try: result = get_list_slice([1, 2, 3, 4, 5], 3) print(f”切片结果: {result}”) get_list_slice(“不是列表”, 3) # 这会抛出异常 except TypeError as e: print(f”错误: {e}”)
  • 在复杂的数据分析任务中,记录函数结果对于调试和监控非常有帮助: def log_results(log_file=”function_results.log”): def decorator(func): def wrapper(*args, **kwargs): result = func(*args, **kwargs) with open(log_file, “a”, encoding=”utf-8″) as f: f.write(f”{func.__name__} – 参数: {args} {kwargs} – 结果: {result}n”) return result return wrapper return decorator @log_results(“calculations.log”) def calculate_statistics(numbers): “””计算数据的统计信息””” if not numbers: return None return { ‘sum’: sum(numbers), ‘mean’: sum(numbers) / len(numbers), ‘max’: max(numbers), ‘min’: min(numbers) } # 使用示例 stats = calculate_statistics([10, 20, 30, 40, 50]) print(f”统计结果: {stats}”)
  • 防止意外错误中断整个执行流程: def suppress_errors(default_return=None): def decorator(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: print(f”函数 {func.__name__} 执行出错: {e}”) return default_return return wrapper return decorator @suppress_errors(default_return=0) def safe_divide(a, b): “””安全的除法运算””” return a / b # 使用示例 print(f”10 / 2 = {safe_divide(10, 2)}”) print(f”10 / 0 = {safe_divide(10, 0)}”) # 不会崩溃,返回默认值0
  • 确保函数输出符合质量标准: def validate_output(validation_func): def decorator(func): def wrapper(*args, **kwargs): result = func(*args, **kwargs) if validation_func(result): return result else: raise ValueError(f”函数 {func.__name__} 的输出未通过验证: {result}”) return wrapper return decorator def is_positive_number(x): “””验证是否为正数””” return isinstance(x, (int, float)) and x > 0 @validate_output(is_positive_number) def process_value(x): “””处理数值,确保返回正数””” return abs(x) + 1 # 使用示例 try: print(f”处理 -5: {process_value(-5)}”) print(f”处理 10: {process_value(10)}”) except ValueError as e: print(f”验证失败: {e}”)
  • 在网络请求等可能临时失败的操作中自动重试: import time import random def retry(max_attempts=3, delay=1, backoff=2): def decorator(func): def wrapper(*args, **kwargs): attempts = 0 current_delay = delay while attempts < max_attempts: try: return func(*args, **kwargs) except Exception as e: attempts += 1 if attempts == max_attempts: raise Exception(f”超过最大重试次数 ({max_attempts}),最后错误: {e}”) print(f”第 {attempts} 次尝试失败,{current_delay} 秒后重试… 错误: {e}”) time.sleep(current_delay) current_delay *= backoff # 指数退避 return wrapper return decorator @retry(max_attempts=3, delay=1) def unreliable_operation(): “””模拟可能失败的操作””” if random.random() < 0.7: # 70% 的失败率 raise Exception(“随机失败!”) return “操作成功!” # 使用示例 try: result = unreliable_operation() print(result) except Exception as e: print(f”最终失败: {e}”)
  • 自动打印函数的输入参数和返回值,简化调试过程: def debug(verbose=True): def decorator(func): def wrapper(*args, **kwargs): if verbose: print(f”🔍 调用 {func.__name__}”) print(f” 参数: {args}”) print(f” 关键字参数: {kwargs}”) result = func(*args, **kwargs) if verbose: print(f” 返回值: {result}”) print(f”✅ {func.__name__} 执行完成n”) return result return wrapper return decorator @debug(verbose=True) def complex_calculation(a, b, coefficient=1.5): “””执行复杂计算””” intermediate = (a ** 2 + b ** 2) ** 0.5 return intermediate * coefficient # 使用示例 result = complex_calculation(3, 4, coefficient=2)
  • 当函数不再推荐使用时,向用户发出警告: import warnings def deprecated(replacement=None): def decorator(func): def wrapper(*args, **kwargs): message = f”函数 ‘{func.__name__}’ 已过时,将在未来版本中移除。” if replacement: message += f” 请使用 ‘{replacement}’ 代替。” warnings.warn(message, DeprecationWarning, stacklevel=2) return func(*args, **kwargs) return wrapper return decorator @deprecated(replacement=”new_data_processor”) def old_data_processor(data): “””旧的数据处理函数””” return [x * 2 for x in data] def new_data_processor(data): “””新的数据处理函数””” return [x ** 2 for x in data] # 使用示例 data = [1, 2, 3, 4, 5] result = old_data_processor(data) # 会显示过时警告 print(f”旧方法结果: {result}”)
  • 为数据分析函数自动生成可视化结果: import matplotlib.pyplot as plt def visualize_results(title=None): def decorator(func): def wrapper(*args, **kwargs): result = func(*args, **kwargs) # 创建可视化 plt.figure(figsize=(10, 6)) if isinstance(result, (list, tuple)): plt.plot(result, marker=’o’, linestyle=’-‘, color=’blue’) plt.xlabel(‘索引’) plt.ylabel(‘值’) elif isinstance(result, dict): keys = list(result.keys()) values = list(result.values()) plt.bar(keys, values, color=’skyblue’) plt.xlabel(‘键’) plt.ylabel(‘值’) plot_title = title or f”{func.__name__} 结果可视化” plt.title(plot_title) plt.grid(True, alpha=0.3) plt.tight_layout() plt.show() return result return wrapper return decorator @visualize_results(“月度销售数据趋势”) def analyze_sales_trend(): “””模拟分析销售趋势””” # 模拟月度销售数据 months = [‘1月’, ‘2月’, ‘3月’, ‘4月’, ‘5月’, ‘6月’] sales = [120, 150, 130, 170, 200, 180] return dict(zip(months, sales)) # 使用示例 sales_data = analyze_sales_trend() print(f”销售数据: {sales_data}”)
  • 这些装饰器展示了 Python 装饰器的强大威力。通过简单的 @ 语法,我们就能为函数添加缓存、日志、验证、重试等复杂功能,而无需修改原始函数代码。 在实际项目中,你可以根据具体需求组合使用这些装饰器,或者创建自己的定制装饰器。掌握装饰器不仅能让你的代码更加简洁优雅,还能显著提升开发效率和代码质量。 使用技巧: 多个装饰器可以堆叠使用,执行顺序是从下往上 使用 functools.wraps 可以保留原函数的元信息 装饰器也可以接受参数,实现更灵活的功能配置 以上就是Python中十个常用的自定义装饰器的使用详解的详细内容,更多关于Python自定义装饰器的资料请关注风君子博客其它相关文章! 您可能感兴趣的文章: python 自定义装饰器使用及原理详解(最新推荐) Python使用自定义装饰器的示例详解 python 自定义装饰器实例详解 Python自定义装饰器原理与用法实例分析
  • 目录
    • 1. @timer – 测量函数执行时间
    • 2. @memoize – 缓存函数结果
    • 3. @validate_input – 参数验证
    • 4. @log_results – 记录函数输出
    • 5. @suppress_errors – 优雅的错误处理
    • 6. @validate_output – 输出验证
    • 7. @retry – 自动重试机制
    • 8. @debug – 调试助手
    • 9. @deprecated – 标记过时函数
    • 10. @visualize_results – 自动可视化
    • 总结

    装饰器是 Python 中一项强大而灵活的功能,它允许我们在不修改原始代码的情况下,为函数或类添加额外的功能。无论是性能优化、调试辅助还是代码健壮性提升,装饰器都能让我们的开发工作事半功倍。

    下面分享 10 个简单但超级有用的自定义装饰器,每一个都配有完整的代码实现和使用示例。

    优化代码性能时,了解函数的执行时间至关重要。@timer 装饰器可以轻松跟踪函数的运行时长:

    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__} 执行耗时: {end_time - start_time:.2f} 秒")
            return result
        return wrapper
    
    @timer
    def process_large_dataset():
        """模拟处理大型数据集"""
        data = [x ** 2 for x in range(1000000)]
        return sum(data)
    
    # 使用示例
    result = process_large_dataset()
    print(f"处理结果: {result}")
    

    对于计算成本高的函数,@memoize 可以缓存结果,避免相同输入的重复计算:

    def memoize(func):
        cache = {}
        
        def wrapper(*args):
            if args in cache:
                print(f"从缓存中获取结果: {args} -> {cache[args]}")
                return cache[args]
            result = func(*args)
            cache[args] = result
            print(f"计算并缓存结果: {args} -> {result}")
            return result
        return wrapper
    
    @memoize
    def fibonacci(n):
        if n <= 1:
            return n
        return fibonacci(n - 1) + fibonacci(n - 2)
    
    # 使用示例
    print(fibonacci(10))  # 第一次计算
    print(fibonacci(10))  # 从缓存获取
    

    确保函数接收到的参数符合预期标准:

    def validate_input(*expected_types):
        def decorator(func):
            def wrapper(*args, **kwargs):
                for i, (arg, expected_type) in enumerate(zip(args, expected_types)):
                    if not isinstance(arg, expected_type):
                        raise TypeError(f"参数 {i} 应该是 {expected_type} 类型,但得到的是 {type(arg)}")
                return func(*args, **kwargs)
            return wrapper
        return decorator
    
    @validate_input(list, int)
    def get_list_slice(data, n):
        """获取列表的前n个元素"""
        return data[:n]
    
    # 使用示例
    try:
        result = get_list_slice([1, 2, 3, 4, 5], 3)
        print(f"切片结果: {result}")
        get_list_slice("不是列表", 3)  # 这会抛出异常
    except TypeError as e:
        print(f"错误: {e}")
    

    在复杂的数据分析任务中,记录函数结果对于调试和监控非常有帮助:

    def log_results(log_file="function_results.log"):
        def decorator(func):
            def wrapper(*args, **kwargs):
                result = func(*args, **kwargs)
                with open(log_file, "a", encoding="utf-8") as f:
                    f.write(f"{func.__name__} - 参数: {args} {kwargs} - 结果: {result}n")
                return result
            return wrapper
        return decorator
    
    @log_results("calculations.log")
    def calculate_statistics(numbers):
        """计算数据的统计信息"""
        if not numbers:
            return None
        return {
            'sum': sum(numbers),
            'mean': sum(numbers) / len(numbers),
            'max': max(numbers),
            'min': min(numbers)
        }
    
    # 使用示例
    stats = calculate_statistics([10, 20, 30, 40, 50])
    print(f"统计结果: {stats}")
    

    防止意外错误中断整个执行流程:

    def suppress_errors(default_return=None):
        def decorator(func):
            def wrapper(*args, **kwargs):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    print(f"函数 {func.__name__} 执行出错: {e}")
                    return default_return
            return wrapper
        return decorator
    
    @suppress_errors(default_return=0)
    def safe_divide(a, b):
        """安全的除法运算"""
        return a / b
    
    # 使用示例
    print(f"10 / 2 = {safe_divide(10, 2)}")
    print(f"10 / 0 = {safe_divide(10, 0)}")  # 不会崩溃,返回默认值0
    

    确保函数输出符合质量标准:

    def validate_output(validation_func):
        def decorator(func):
            def wrapper(*args, **kwargs):
                result = func(*args, **kwargs)
                if validation_func(result):
                    return result
                else:
                    raise ValueError(f"函数 {func.__name__} 的输出未通过验证: {result}")
            return wrapper
        return decorator
    
    def is_positive_number(x):
        """验证是否为正数"""
        return isinstance(x, (int, float)) and x > 0
    
    @validate_output(is_positive_number)
    def process_value(x):
        """处理数值,确保返回正数"""
        return abs(x) + 1
    
    # 使用示例
    try:
        print(f"处理 -5: {process_value(-5)}")
        print(f"处理 10: {process_value(10)}")
    except ValueError as e:
        print(f"验证失败: {e}")
    

    在网络请求等可能临时失败的操作中自动重试:

    import time
    import random
    
    def retry(max_attempts=3, delay=1, backoff=2):
        def decorator(func):
            def wrapper(*args, **kwargs):
                attempts = 0
                current_delay = delay
                
                while attempts < max_attempts:
                    try:
                        return func(*args, **kwargs)
                    except Exception as e:
                        attempts += 1
                        if attempts == max_attempts:
                            raise Exception(f"超过最大重试次数 ({max_attempts}),最后错误: {e}")
                        
                        print(f"第 {attempts} 次尝试失败,{current_delay} 秒后重试... 错误: {e}")
                        time.sleep(current_delay)
                        current_delay *= backoff  # 指数退避
                return wrapper
        return decorator
    
    @retry(max_attempts=3, delay=1)
    def unreliable_operation():
        """模拟可能失败的操作"""
        if random.random() < 0.7:  # 70% 的失败率
            raise Exception("随机失败!")
        return "操作成功!"
    
    # 使用示例
    try:
        result = unreliable_operation()
        print(result)
    except Exception as e:
        print(f"最终失败: {e}")
    

    自动打印函数的输入参数和返回值,简化调试过程:

    def debug(verbose=True):
        def decorator(func):
            def wrapper(*args, **kwargs):
                if verbose:
                    print(f"🔍 调用 {func.__name__}")
                    print(f"   参数: {args}")
                    print(f"   关键字参数: {kwargs}")
                
                result = func(*args, **kwargs)
                
                if verbose:
                    print(f"   返回值: {result}")
                    print(f"✅ {func.__name__} 执行完成n")
                
                return result
            return wrapper
        return decorator
    
    @debug(verbose=True)
    def complex_calculation(a, b, coefficient=1.5):
        """执行复杂计算"""
        intermediate = (a ** 2 + b ** 2) ** 0.5
        return intermediate * coefficient
    
    # 使用示例
    result = complex_calculation(3, 4, coefficient=2)
    

    当函数不再推荐使用时,向用户发出警告:

    import warnings
    
    def deprecated(replacement=None):
        def decorator(func):
            def wrapper(*args, **kwargs):
                message = f"函数 '{func.__name__}' 已过时,将在未来版本中移除。"
                if replacement:
                    message += f" 请使用 '{replacement}' 代替。"
                
                warnings.warn(message, DeprecationWarning, stacklevel=2)
                return func(*args, **kwargs)
            return wrapper
        return decorator
    
    @deprecated(replacement="new_data_processor")
    def old_data_processor(data):
        """旧的数据处理函数"""
        return [x * 2 for x in data]
    
    def new_data_processor(data):
        """新的数据处理函数"""
        return [x ** 2 for x in data]
    
    # 使用示例
    data = [1, 2, 3, 4, 5]
    result = old_data_processor(data)  # 会显示过时警告
    print(f"旧方法结果: {result}")
    

    为数据分析函数自动生成可视化结果:

    import matplotlib.pyplot as plt
    
    def visualize_results(title=None):
        def decorator(func):
            def wrapper(*args, **kwargs):
                result = func(*args, **kwargs)
                
                # 创建可视化
                plt.figure(figsize=(10, 6))
                
                if isinstance(result, (list, tuple)):
                    plt.plot(result, marker='o', linestyle='-', color='blue')
                    plt.xlabel('索引')
                    plt.ylabel('值')
                elif isinstance(result, dict):
                    keys = list(result.keys())
                    values = list(result.values())
                    plt.bar(keys, values, color='skyblue')
                    plt.xlabel('键')
                    plt.ylabel('值')
                
                plot_title = title or f"{func.__name__} 结果可视化"
                plt.title(plot_title)
                plt.grid(True, alpha=0.3)
                plt.tight_layout()
                plt.show()
                
                return result
            return wrapper
        return decorator
    
    @visualize_results("月度销售数据趋势")
    def analyze_sales_trend():
        """模拟分析销售趋势"""
        # 模拟月度销售数据
        months = ['1月', '2月', '3月', '4月', '5月', '6月']
        sales = [120, 150, 130, 170, 200, 180]
        return dict(zip(months, sales))
    
    # 使用示例
    sales_data = analyze_sales_trend()
    print(f"销售数据: {sales_data}")
    

    这些装饰器展示了 Python 装饰器的强大威力。通过简单的 @ 语法,我们就能为函数添加缓存、日志、验证、重试等复杂功能,而无需修改原始函数代码。

    在实际项目中,你可以根据具体需求组合使用这些装饰器,或者创建自己的定制装饰器。掌握装饰器不仅能让你的代码更加简洁优雅,还能显著提升开发效率和代码质量。

    使用技巧:

    • 多个装饰器可以堆叠使用,执行顺序是从下往上
    • 使用 functools.wraps 可以保留原函数的元信息
    • 装饰器也可以接受参数,实现更灵活的功能配置

    以上就是Python中十个常用的自定义装饰器的使用详解的详细内容,更多关于Python自定义装饰器的资料请关注风君子博客其它相关文章!

    您可能感兴趣的文章:

    • python 自定义装饰器使用及原理详解(最新推荐)
    • Python使用自定义装饰器的示例详解
    • python 自定义装饰器实例详解
    • Python自定义装饰器原理与用法实例分析

    站内搜索