全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-19 6 分钟 ✍️ juanwangdev

Python 装饰器堆叠

多个装饰器可以同时应用到一个函数上,形成装饰器堆叠。

基本语法

Python
@decorator1
@decorator2
@decorator3
def func():
    pass

# 等价于
func = decorator1(decorator2(decorator3(func)))

执行顺序

应用顺序(从下到上)

装饰器按从下到上的顺序应用:

Python
def decorator_a(func):
    print("A 应用")
    def wrapper(*args, **kwargs):
        print("A 执行前")
        result = func(*args, **kwargs)
        print("A 执行后")
        return result
    return wrapper


def decorator_b(func):
    print("B 应用")
    def wrapper(*args, **kwargs):
        print("B 执行前")
        result = func(*args, **kwargs)
        print("B 执行后")
        return result
    return wrapper


@decorator_a
@decorator_b
def greet(name):
    print(f"Hello, {name}!")

# 输出:
# B 应用
# A 应用

执行顺序(从外到内)

调用时,最外层装饰器先执行:

Python
greet("World")

# 输出:
# A 执行前
# B 执行前
# Hello, World!
# B 执行后
# A 执行后

执行流程图

Python
应用阶段(定义时):
func → decorator_b(func) → wrapper_b
wrapper_b → decorator_a(wrapper_b) → wrapper_a

执行阶段(调用时):
wrapper_a() → print("A 执行前")
           → wrapper_b() → print("B 执行前")
                        → func() → print("Hello")
                        → print("B 执行后")
           → print("A 执行后")

实际应用场景

日志 + 计时

Python
import time
from functools import wraps


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


def timer(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        print(f"耗时: {time.perf_counter() - start:.4f}s")
        return result
    return wrapper


@log
@timer
def process_data(n):
    "处理数据"
    time.sleep(n)
    return n * 2


process_data(0.1)
# 调用: process_data
# 耗时: 0.1005s

缓存 + 验证

Python
def cache(func):
    "简单缓存装饰器"
    cached = {}

    @wraps(func)
    def wrapper(*args):
        if args not in cached:
            cached[args] = func(*args)
        return cached[args]
    return wrapper


def validate(func):
    "参数验证装饰器"
    @wraps(func)
    def wrapper(*args):
        if any(arg < 0 for arg in args):
            raise ValueError("参数不能为负数")
        return func(*args)
    return wrapper


@cache
@validate
def multiply(a, b):
    return a * b


multiply(3, 4)   # 12,计算并缓存
multiply(3, 4)   # 12,从缓存读取
multiply(-1, 2)  # ValueError

重试 + 异常处理

Python
def retry(attempts=3):
    "重试装饰器"
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for i in range(attempts):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if i == attempts - 1:
                        raise
                    print(f"重试 {i + 1}/{attempts}")
        return wrapper
    return decorator


def handle_errors(default=None):
    "异常处理装饰器"
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                print(f"错误: {e}")
                return default
        return wrapper
    return decorator


@handle_errors(default="failed")
@retry(attempts=2)
def risky_operation(data):
    if data < 0:
        raise ValueError("负数错误")
    return data * 10


risky_operation(5)   # 50
risky_operation(-1)  # 重试后返回 "failed"

堆叠顺序的影响

不同顺序产生不同效果:

text
# 顺序A:先验证后缓存
@cache
@validate
def func(x):
    return x * 2

# 顺序B:先缓存后验证
@validate
@cache
def func(x):
    return x * 2
顺序效果
先 validate 后 cache验证通过才缓存,缓存数据可靠
先 cache 后 validate可能缓存无效数据

要点总结

规则说明
应用顺序从下到上,最下面的装饰器最先应用
执行顺序从外到内,最外层装饰器最先执行
等价形式@a @b def f() 等于 f = a(b(f))
设计原则根据功能依赖关系决定顺序

装饰器堆叠顺序至关重要:应用时从下到上,执行时从外到内,类似洋葱结构。

D:\git2\jwdev\articles\PYTHON\进阶\装饰器深入\装饰器堆叠.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 Python 类装饰器
下一篇 → Python __enter__ 与 __exit__ 方法
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库