Python中的函数装饰器参数传递与多层装饰器执行顺序
字数 519 2025-11-24 11:49:07

Python中的函数装饰器参数传递与多层装饰器执行顺序

知识点描述
装饰器是Python中用于修改或增强函数行为的强大工具。当装饰器本身需要参数,或者多个装饰器堆叠使用时,参数传递和执行顺序就变得复杂。理解装饰器参数如何传递以及多层装饰器的执行顺序,对于编写和调试装饰器代码至关重要。

详细讲解

1. 基础装饰器回顾
首先回忆简单装饰器的结构:

def decorator(func):
    def wrapper(*args, **kwargs):
        # 增强功能
        result = func(*args, **kwargs)
        # 后续处理
        return result
    return wrapper

@decorator
def target_function():
    pass

这里的@decorator是语法糖,等价于target_function = decorator(target_function)

2. 带参数的装饰器
当装饰器本身需要接收参数时,需要三层嵌套函数:

def repeat(num_times):  # 第一层:接收装饰器参数
    def decorator(func):  # 第二层:接收被装饰函数
        def wrapper(*args, **kwargs):  # 第三层:接收函数参数
            for _ in range(num_times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(num_times=3)
def greet(name):
    print(f"Hello {name}")

# 执行过程分解:
# 1. repeat(3) 返回decorator函数
# 2. decorator(greet) 返回wrapper函数  
# 3. 实际调用的是wrapper("Alice")

3. 多层装饰器的执行顺序
当多个装饰器堆叠时,执行顺序是从下往上装饰,从上往下执行

def decorator1(func):
    print("decorator1 applied")
    def wrapper():
        print("decorator1 before")
        func()
        print("decorator1 after")
    return wrapper

def decorator2(func):
    print("decorator2 applied")  
    def wrapper():
        print("decorator2 before")
        func()
        print("decorator2 after")
    return wrapper

@decorator1
@decorator2
def original():
    print("original function")

# 装饰阶段(从下往上):
# 1. original = decorator2(original) → 打印"decorator2 applied"
# 2. original = decorator1(original) → 打印"decorator1 applied"

# 调用original()时的执行顺序(从上往下):
# decorator1 before
# decorator2 before  
# original function
# decorator2 after
# decorator1 after

4. 复杂情况:带参数的多层装饰器
结合前两种情况,分析最复杂的场景:

def validate_input(validator):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if not validator(*args, **kwargs):
                raise ValueError("Invalid input")
            return func(*args, **kwargs)
        return wrapper
    return decorator

def log_call(level="INFO"):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(f"[{level}] Calling {func.__name__}")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@validate_input(lambda x: x > 0)  # 最外层装饰器
@log_call(level="DEBUG")          # 中间层装饰器  
def calculate_square(x):
    return x * x

# 装饰过程分解:
# 1. log_call("DEBUG")返回decorator_l1
# 2. decorator_l1(calculate_square)返回wrapper_l1
# 3. validate_input(lambda x: x > 0)返回decorator_v1  
# 4. decorator_v1(wrapper_l1)返回最终的wrapper_v1

# 调用calculate_square(2)时的执行流:
# 1. validate_input的wrapper检查参数
# 2. log_call的wrapper打印日志
# 3. 执行原始函数calculate_square

5. 使用functools.wraps保持元信息
为了避免装饰器掩盖原函数的元信息,应该使用functools.wraps

from functools import wraps

def decorator(func):
    @wraps(func)  # 将原函数的元信息复制到wrapper
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

关键要点总结

  • 装饰器参数传递需要三层嵌套函数结构
  • 多层装饰器装饰时从下往上,执行时从上往下
  • 使用@wraps保持函数元信息
  • 理解装饰器的实际等价转换有助于调试复杂情况
Python中的函数装饰器参数传递与多层装饰器执行顺序 知识点描述 装饰器是Python中用于修改或增强函数行为的强大工具。当装饰器本身需要参数,或者多个装饰器堆叠使用时,参数传递和执行顺序就变得复杂。理解装饰器参数如何传递以及多层装饰器的执行顺序,对于编写和调试装饰器代码至关重要。 详细讲解 1. 基础装饰器回顾 首先回忆简单装饰器的结构: 这里的 @decorator 是语法糖,等价于 target_function = decorator(target_function) 。 2. 带参数的装饰器 当装饰器本身需要接收参数时,需要三层嵌套函数: 3. 多层装饰器的执行顺序 当多个装饰器堆叠时,执行顺序是 从下往上装饰,从上往下执行 : 4. 复杂情况:带参数的多层装饰器 结合前两种情况,分析最复杂的场景: 5. 使用functools.wraps保持元信息 为了避免装饰器掩盖原函数的元信息,应该使用 functools.wraps : 关键要点总结 装饰器参数传递需要三层嵌套函数结构 多层装饰器装饰时从下往上,执行时从上往下 使用 @wraps 保持函数元信息 理解装饰器的实际等价转换有助于调试复杂情况