如何实现参数化装饰器

PythonBeginner
立即练习

简介

Python 装饰器是用于修改和增强函数行为的强大工具。本教程将探讨创建参数化装饰器的高级技术,它允许开发者使用灵活的参数和复杂的转换逻辑来动态配置函数包装器。

装饰器基础

什么是装饰器?

在 Python 中,装饰器是一种强大的设计模式,它允许你在不直接更改函数和方法源代码的情况下对其进行修改或增强。本质上,装饰器是一种函数,它接受另一个函数作为参数,并返回该函数的修改版本。

基本装饰器语法

def simple_decorator(func):
    def wrapper():
        print("函数调用前执行某些操作。")
        func()
        print("函数调用后执行某些操作。")
    return wrapper

@simple_decorator
def say_hello():
    print("你好,LabEx!")

say_hello()

装饰器的关键特性

特性 描述
函数修改 允许动态修改函数行为
非侵入性 不改变原始函数的源代码
可重用性 可应用于多个函数

装饰器的工作原理

graph LR A[原始函数] --> B[装饰器函数] B --> C[包装函数] C --> D[增强的功能]

装饰器的类型

  1. 函数装饰器:修改单个函数
  2. 类装饰器:修改整个类
  3. 方法装饰器:修改类方法

实际示例

def timer_decorator(func):
    import time
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"函数 {func.__name__} 执行耗时 {end_time - start_time} 秒")
        return result
    return wrapper

@timer_decorator
def complex_calculation():
    return sum(range(1000000))

complex_calculation()

常见用例

  • 日志记录
  • 性能测量
  • 认证
  • 缓存
  • 输入验证

最佳实践

  • 保持装饰器简单且功能集中
  • 使用 functools.wraps 保留原始函数的元数据
  • 了解装饰器对性能的影响

通过理解这些基础知识,开发者可以利用装饰器,按照 LabEx 推荐的编写简洁、可维护代码的方法,编写更模块化、高效的 Python 代码。

参数化装饰器设计

理解参数化装饰器

参数化装饰器是一种高级装饰器函数,它可以接受参数,从而实现更灵活、可配置的函数修改。

参数化装饰器的基本结构

def decorator_with_args(arg1, arg2):
    def actual_decorator(func):
        def wrapper(*args, **kwargs):
            ## 使用 arg1 和 arg2 的装饰器逻辑
            print(f"装饰器参数: {arg1}, {arg2}")
            return func(*args, **kwargs)
        return wrapper
    return actual_decorator

装饰器参数模式

模式 描述 用例
配置 修改装饰器行为 日志级别
验证 添加输入检查 参数约束
转换 修改函数输入/输出 数据预处理

实际实现示例

def repeat(times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(times=3)
def greet(name):
    print(f"你好, {name}!")

greet("LabEx")

装饰器组合流程

graph LR A[装饰器参数] --> B[装饰器工厂] B --> C[实际装饰器] C --> D[包装函数] D --> E[增强的功能]

高级参数化装饰器技术

条件装饰

def conditional_decorator(condition):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if condition:
                print("条件满足,应用装饰器")
                return func(*args, **kwargs)
            return func(*args, **kwargs)
        return wrapper
    return decorator

@conditional_decorator(condition=True)
def example_function():
    print("函数执行")

常见用例

  1. 具有可配置详细程度的日志记录
  2. 具有自定义过期时间的缓存
  3. 速率限制
  4. 性能监控
  5. 输入验证

最佳实践

  • 保持装饰器逻辑简洁
  • 使用 functools.wraps 保留函数元数据
  • 确保类型安全和错误处理
  • 考虑性能影响

参数化装饰器中的错误处理

def validate_type(expected_type):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for arg in args:
                if not isinstance(arg, expected_type):
                    raise TypeError(f"期望类型为 {expected_type},得到的类型为 {type(arg)}")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@validate_type(int)
def add_numbers(a, b):
    return a + b

通过掌握参数化装饰器,开发者可以运用 LabEx 的高级编程技术创建更具动态性和灵活性的 Python 代码。

实际应用

性能监控装饰器

import time
import functools

def performance_monitor(func):
    @functools.wraps(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} 秒")
        return result
    return wrapper

@performance_monitor
def complex_calculation(n):
    return sum(range(n))

complex_calculation(1000000)

认证和授权装饰器

def require_auth(roles):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(user, *args, **kwargs):
            if user.role in roles:
                return func(user, *args, **kwargs)
            raise PermissionError("未经授权的访问")
        return wrapper
    return decorator

class User:
    def __init__(self, name, role):
        self.name = name
        self.role = role

@require_auth(['admin','manager'])
def delete_user(user, user_id):
    print(f"用户 {user_id} 被 {user.name} 删除")

admin = User("Alice", "admin")
delete_user(admin, 123)

带过期时间的缓存装饰器

from functools import wraps
import time

def cache_with_expiry(expiry_seconds):
    def decorator(func):
        cache = {}
        def wrapper(*args, **kwargs):
            key = str(args) + str(kwargs)
            current_time = time.time()

            if key in cache:
                result, timestamp = cache[key]
                if current_time - timestamp < expiry_seconds:
                    return result

            result = func(*args, **kwargs)
            cache[key] = (result, current_time)
            return result
        return wrapper
    return decorator

@cache_with_expiry(expiry_seconds=5)
def expensive_computation(x, y):
    time.sleep(2)
    return x + y

装饰器应用场景

场景 装饰器用途 主要优点
日志记录 跟踪函数调用 审计线索
重试机制 处理临时故障 弹性
输入验证 确保数据完整性 错误预防
速率限制 控制 API 使用 资源管理

重试机制装饰器

def retry(max_attempts=3, delay=1):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            attempts = 0
            while attempts < max_attempts:
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    attempts += 1
                    if attempts == max_attempts:
                        raise
                    time.sleep(delay)
        return wrapper
    return decorator

@retry(max_attempts=3, delay=2)
def unreliable_network_call():
    ## 模拟网络请求
    import random
    if random.random() < 0.7:
        raise ConnectionError("网络错误")
    return "成功"

装饰器工作流程

graph LR A[函数调用] --> B{装饰器检查} B --> |通过| C[原始函数] B --> |失败| D[错误处理] C --> E[返回结果] D --> F[替代操作]

高级日志记录装饰器

import logging
import functools

def log_calls(log_level=logging.INFO):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            logging.log(log_level, f"调用 {func.__name__}")
            try:
                result = func(*args, **kwargs)
                logging.log(log_level, f"{func.__name__} 成功完成")
                return result
            except Exception as e:
                logging.error(f"{func.__name__} 引发 {type(e).__name__}: {e}")
                raise
        return wrapper
    return decorator

@log_calls(log_level=logging.DEBUG)
def process_data(data):
    ## 数据处理逻辑
    pass

通过探索这些实际应用,开发者可以利用装饰器,运用 LabEx 的高级编程技术创建更健壮、可维护的代码。

总结

通过掌握 Python 中的参数化装饰器,开发者可以创建更模块化、可重用和适应性更强的代码。这些高级技术能够实现复杂的函数操作,为诸如日志记录、认证和不同编程场景下的性能监控等横切关注点提供优雅的解决方案。