跳转到内容

Python 装饰器高级用法

来自代码酷
Admin留言 | 贡献2025年4月28日 (一) 21:11的版本 (Page update by admin bot)

(差异) ←上一版本 | 已核准修订 (差异) | 最后版本 (差异) | 下一版本→ (差异)

Python装饰器高级用法[编辑 | 编辑源代码]

装饰器是Python函数式编程中的核心概念之一,它允许在不修改原函数代码的情况下,动态地扩展函数的行为。装饰器本质上是一个高阶函数,它接受一个函数作为参数并返回一个新的函数。本节将深入探讨装饰器的高级用法,包括带参数的装饰器、类装饰器、装饰器堆叠以及实际应用场景。

1. 装饰器基础回顾[编辑 | 编辑源代码]

装饰器的基本语法如下:

def decorator(func):
    def wrapper(*args, **kwargs):
        # 前置操作
        result = func(*args, **kwargs)
        # 后置操作
        return result
    return wrapper

@decorator
def target_function():
    pass

当调用target_function()时,实际上执行的是decorator(target_function)()

2. 带参数的装饰器[编辑 | 编辑源代码]

装饰器本身也可以接受参数,这需要再嵌套一层函数:

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"Hello, {name}!")

greet("Alice")

输出:

Hello, Alice!
Hello, Alice!
Hello, Alice!

3. 类装饰器[编辑 | 编辑源代码]

类也可以作为装饰器,只需实现__call__方法:

class Timer:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        import time
        start = time.time()
        result = self.func(*args, **kwargs)
        end = time.time()
        print(f"{self.func.__name__} executed in {end-start:.4f}s")
        return result

@Timer
def factorial(n):
    return 1 if n <= 1 else n * factorial(n-1)

print(factorial(5))

输出:

factorial executed in 0.0001s
factorial executed in 0.0002s
...
120

4. 装饰器堆叠[编辑 | 编辑源代码]

多个装饰器可以堆叠使用,执行顺序是从下往上:

@decorator1
@decorator2
@decorator3
def function():
    pass

等价于: function = decorator1(decorator2(decorator3(function)))

5. 保留元信息[编辑 | 编辑源代码]

使用functools.wraps保留原函数的元信息:

from functools import wraps

def log_execution(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"Executing {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

6. 实际应用案例[编辑 | 编辑源代码]

6.1 权限验证[编辑 | 编辑源代码]

def requires_admin(func):
    @wraps(func)
    def wrapper(user, *args, **kwargs):
        if not user.is_admin:
            raise PermissionError("Admin rights required")
        return func(user, *args, **kwargs)
    return wrapper

6.2 缓存装饰器[编辑 | 编辑源代码]

from functools import lru_cache

@lru_cache(maxsize=128)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

7. 高级模式:装饰器工厂[编辑 | 编辑源代码]

装饰器工厂可以动态生成装饰器:

def validate_input(*validators):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for i, (arg, validator) in enumerate(zip(args, validators)):
                if not validator(arg):
                    raise ValueError(f"Argument {i} invalid")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@validate_input(lambda x: x > 0, lambda y: isinstance(y, str))
def process_data(num, text):
    return text * num

8. 执行流程可视化[编辑 | 编辑源代码]

graph LR A[调用装饰函数] --> B[执行装饰器外层逻辑] B --> C[调用原函数] C --> D[执行原函数逻辑] D --> E[返回结果到装饰器] E --> F[执行装饰器剩余逻辑] F --> G[返回最终结果]

9. 数学表达[编辑 | 编辑源代码]

装饰器的数学本质可以表示为: decorator(f)=gfh 其中表示函数组合。

10. 最佳实践[编辑 | 编辑源代码]

  • 始终使用functools.wraps保留元信息
  • 避免在装饰器中修改传入的参数
  • 装饰器的逻辑应保持简洁单一
  • 考虑使用类装饰器处理复杂状态

通过掌握这些高级技巧,你可以创建出更灵活、更强大的装饰器,显著提升代码的可重用性和可维护性。