开发者

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 个简单但超级有用的自定义装饰器,每一个都配有完整的代码实现和使用示例。

1. @timer - 测量函数执行时间

优化代码性能时,了解函数的执行时间至关重要。@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:.2phpf} 秒")
        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}")

2. @memoize - 缓存函数结果

对于计算成本高的函数,@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))  # 从缓存获取

3. @validate_input - 参数验证

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

def validate_input(*expected_types):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for i, (arg, expected_type) in enumerate(zip(args, expected_types)):
              http://www.devze.com  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 = www.devze.comget_list_slice([1, 2, 3, 4, 5], 3)
    print(f"切片结果: {result}")
    get_list_slice("不是列表", 3)  # 这会抛出异常
except TypeError as e:
    print(f"错误: {e}")

4. @log_results - 记录函数输出

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

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])
printandroid(f"统计结果: {stats}")

5. @suppress_errors - 优雅的错误处理

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

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

6. @validate_output - 输出验证

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

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}")

7. @retry - 自动重试机制

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

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}")

8. @debug - 调试助手

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

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)php
            
            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)

9. @deprecated - 标记过时函数

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

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}")

10. @visualize_results - 自动可视化

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

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自定义装饰器的资料请关注编程客栈(www.devze.com)其它相关文章!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新开发

开发排行榜