Python多个装饰器叠加时执行顺序是怎样的

来源:建站作者:新井头衔:网络博主
导读:本期聚焦于小伙伴创作的《Python多个装饰器叠加时执行顺序是怎样的》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Python多个装饰器叠加时执行顺序是怎样的》有用,将其分享出去将是对创作者最好的鼓励。

Python中的装饰器是一种非常实用的语法特性,可以在不修改原函数代码的前提下扩展函数的功能。当同一个函数被多个装饰器修饰时,其执行顺序遵循固定的规则,理解这个规则能帮助我们更好地使用装饰器实现复杂的功能扩展。

Python多个装饰器叠加时执行顺序是怎样的

装饰器的基本工作原理

装饰器的本质是一个接收函数作为参数,并返回一个新函数的高阶函数。当我们使用@装饰器名语法修饰函数时,等价于将原函数作为参数传入装饰器,再用装饰器返回的新函数替换原函数。

下面是一个最简单的装饰器示例:

def simple_decorator(func):
    def wrapper():
        print("装饰器前置逻辑")
        func()
        print("装饰器后置逻辑")
    return wrapper

@simple_decorator
def test_func():
    print("原函数逻辑")

# 等价于 test_func = simple_decorator(test_func)
test_func()

上述代码执行后会依次输出:装饰器前置逻辑、原函数逻辑、装饰器后置逻辑,说明装饰器会在原函数执行前后插入自定义逻辑。

多个装饰器叠加的执行顺序规则

当同一个函数被多个装饰器修饰时,装饰器的加载顺序是从下到上,而执行顺序是从上到下。也就是说,离函数定义最近的装饰器会先被加载,但是它的内部逻辑会在所有装饰器加载完成后,按照从外到内的顺序执行。

加载顺序验证

我们可以通过在装饰器内部添加打印语句来验证加载顺序,示例代码如下:

def decorator_a(func):
    print("装饰器A加载完成")
    def wrapper():
        print("进入装饰器A的逻辑")
        func()
        print("离开装饰器A的逻辑")
    return wrapper

def decorator_b(func):
    print("装饰器B加载完成")
    def wrapper():
        print("进入装饰器B的逻辑")
        func()
        print("离开装饰器B的逻辑")
    return wrapper

@decorator_a
@decorator_b
def multi_decorator_func():
    print("原函数执行")

print("开始调用函数")
multi_decorator_func()

上述代码的输出结果如下:

装饰器B加载完成
装饰器A加载完成
开始调用函数
进入装饰器A的逻辑
进入装饰器B的逻辑
原函数执行
离开装饰器B的逻辑
离开装饰器A的逻辑

从输出可以看到,先打印的是装饰器B加载完成,再打印装饰器A加载完成,说明加载顺序是从下到上,先加载离函数近的decorator_b,再加载decorator_a。

执行顺序原理分析

多个装饰器叠加的语法本质是嵌套调用,@decorator_a @decorator_b def func()等价于:

# 先执行 decorator_b(func),得到b_wrapper
b_wrapper = decorator_b(multi_decorator_func)
# 再执行 decorator_a(b_wrapper),得到a_wrapper
a_wrapper = decorator_a(b_wrapper)
# 最终 multi_decorator_func 指向 a_wrapper
multi_decorator_func = a_wrapper

当我们调用multi_decorator_func()时,实际是调用a_wrapper(),而a_wrapper内部的func()调用的是b_wrapper()b_wrapper内部的func()才是真正的原函数,因此执行顺序就是先走decorator_a的前置逻辑,再走decorator_b的前置逻辑,然后执行原函数,之后走decorator_b的后置逻辑,最后走decorator_a的后置逻辑。

带参数的装饰器叠加顺序

如果装饰器本身带参数,执行顺序的规则依然不变,只是加载时需要先传入参数再处理原函数。示例代码如下:

def decorator_with_args(arg):
    print(f"带参数装饰器加载,参数:{arg}")
    def outer(func):
        def wrapper():
            print(f"进入带参数装饰器,参数:{arg}")
            func()
            print(f"离开带参数装饰器,参数:{arg}")
        return wrapper
    return outer

@decorator_with_args("A")
@decorator_with_args("B")
def func_with_args():
    print("带参数的原函数执行")

func_with_args()

上述代码的输出结果如下:

带参数装饰器加载,参数:B
带参数装饰器加载,参数:A
进入带参数装饰器,参数:A
进入带参数装饰器,参数:B
带参数的原函数执行
离开带参数装饰器,参数:B
离开带参数装饰器,参数:A

可以看到带参数的装饰器同样遵循加载从下到上,执行从上到下的规则。

注意事项

  • 装饰器的加载发生在函数定义阶段,也就是模块导入的时候就会执行装饰器的外层逻辑,而不是函数调用的时候。
  • 如果多个装饰器之间有依赖关系,需要根据执行顺序合理排列装饰器的位置,避免出现逻辑错误。
  • 使用functools.wraps可以保留原函数的元信息,在多个装饰器叠加时也需要为每个wrapper函数添加该装饰器,避免原函数的名称、文档等信息被覆盖。

以下是一个使用functools.wraps的正确示例:

import functools

def decorator_one(func):
    @functools.wraps(func)
    def wrapper():
        print("装饰器1逻辑")
        func()
    return wrapper

def decorator_two(func):
    @functools.wraps(func)
    def wrapper():
        print("装饰器2逻辑")
        func()
    return wrapper

@decorator_one
@decorator_two
def demo():
    print("demo函数")

print(demo.__name__)  # 输出 demo,而不是wrapper

Python装饰器装饰器叠加执行顺序修改时间:2026-06-11 18:45:16

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。