讲师中心 微信公众号
AI工具推荐 视频效率加速

Python 装饰器的执行顺序解析

云墨吖_6423

云墨吖_6423

发布时间:2026-01-27 18:17:55

|

157人浏览过

|

来源于php中文网

原创

装饰器在函数定义时就完成包装,即模块加载时执行@decorator等价于func=decorator(func);带参装饰器需三层嵌套,多装饰器按从下到上顺序嵌套,须用functools.wraps保留元信息。

python 装饰器的执行顺序解析

装饰器在函数定义时就完成包装

Python 装饰器不是在函数调用时才起作用,而是在 @ 语法解析阶段、函数对象被创建后立即执行。这意味着 @decorator 实际等价于 func = decorator(func),且该赋值发生在模块加载时。

常见错误现象:在装饰器内部打印日志却没看到输出——很可能是因为模块没被导入,或者装饰器写成了带括号形式但未正确返回可调用对象。

  • 如果写成 @my_decorator(),必须确保 my_decorator() 返回一个接收函数的闭包
  • 装饰器链如 @a @b def f(): ... 等价于 f = a(b(f)),即从下往上套用(b 先包,再被 a 包)
  • 类装饰器需实现 __call__ 方法;函数装饰器返回的必须是可调用对象

带参数的装饰器要多嵌套一层

当你看到 @retry(max_attempts=3) 这种带参数的写法,它背后其实是三层函数结构:最外层接收装饰器参数,中间层接收被装饰函数,最内层才是实际执行逻辑。

容易踩的坑是漏掉某一层返回,导致 TypeError: 'NoneType' object is not callable。

立即学习“Python免费学习笔记(深入)”;

  • 典型骨架:def retry(max_attempts): → def decorator(func): → def wrapper(*args, **kwargs): → return wrapper → return decorator
  • 若中间层忘记 return decorator,则 @retry(...) 展开后得到的是 None,后续绑定失败
  • 使用 functools.wraps(func) 在 wrapper 内部保留原函数元信息,否则 help(f) 或序列化会出问题

多个装饰器叠加时注意执行顺序和作用域

装饰器叠加不是“并行生效”,而是形成嵌套调用链。外层装饰器的 wrapper 调用内层装饰器的 wrapper,最终才到原始函数。

python学习
python学习

Python 编程学习助手 skill,面向零基础用户。 当用户表达以下意图时触发: - 学习 Python 基础概念(变量、数据类型、循环、函数、类等) - 请求 Python 练习题或测验 - 请求审查或调试 Python 代码 - 请求 Python 项目实战指导(爬虫、数据分析、Web 开发等入门项目) - 泛化表述如"教我 Python""我想学编程""Python 怎么写""帮我学 Python" 此 skill

下载

这意味着:前置逻辑按装饰器声明顺序从上到下执行,后置逻辑则反过来(类似栈的压入与弹出)。

def log_calls(func):
    def wrapper(*args):
        print(f"→ calling {func.__name__}")
        result = func(*args)
        print(f"← done {func.__name__}")
        return result
    return wrapper

def add_prefix(func):
    def wrapper(*args):
        print("[prefix] before")
        result = func(*args)
        print("[prefix] after")
        return result
    return wrapper

@log_calls
@add_prefix
def say(x):
    return f"hello {x}"

调用 say("world") 输出顺序为:→ calling say → [prefix] before → [prefix] after → ← done say。可见 log_calls 的前后逻辑包裹了整个 add_prefix 流程。

装饰器中访问闭包变量或 self 容易引发状态混淆

装饰器本身是模块级代码,其内部定义的变量(如计数器、缓存字典)在所有被装饰函数间共享。如果是类方法装饰器,还可能误把实例状态当成装饰器状态。

典型错误:用一个全局字典记录调用次数,结果多个函数共用同一计数器;或在类装饰器里把 self 当作被装饰方法的实例传入。

  • 避免全局状态污染:每个被装饰函数应有独立上下文,可用 functools.partial 或闭包绑定专属数据
  • 装饰实例方法时,wrapper 接收的第一个参数是 self,但该 self 是调用时的对象,不是装饰器类的 self
  • 若需绑定实例生命周期,考虑用描述符(descriptor)替代函数装饰器

真正麻烦的从来不是语法怎么写,而是哪一层 closure 捕获了哪个变量,以及那个变量是不是你认为的那个“它”。

热门AI工具

更多
PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

6167

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2608

2023.08.10

go语言闭包相关教程大全
go语言闭包相关教程大全

本专题整合了go语言闭包相关数据,阅读专题下面的文章了解更多相关内容。

4593

2025.07.29

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

100

2026.10.22

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

60

2026.10.22

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

60

2026.10.22

Gradle怎么构建Java项目
Gradle怎么构建Java项目

本专题介绍Gradle Java项目构建方法,涵盖Java插件配置、依赖声明、源码编译、测试执行和打包检查,帮助你理解各阶段的任务关系,逐步完成项目构建。

20

2026.10.22

PHP时间戳漏洞修复教程
PHP时间戳漏洞修复教程

本专题汇总PHP常见时间戳漏洞,包括2038年溢出、时区漂移、时间戳伪造、重放攻击、时间盲注与日志审计失效等,并给出升级64位环境、使用 DateTimeImmutable、统一UTC、严格超时校验、预处理绑定、hash_equals 比对等修复方案,帮助开发者快速排查和加固时间相关代码。

60

2026.10.22

Golangci-lint配置文件与规则设置
Golangci-lint配置文件与规则设置

本专题聚焦Golangci-lint YAML配置文件,讲清运行参数、规则启停、目录排除、问题过滤及严重级别设置,便于团队统一检查标准。

20

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Uvicorn官方安装与入门手册
Uvicorn官方安装与入门手册

共0课时 | 0人学习

Python uv官方项目管理指南
Python uv官方项目管理指南

共0课时 | 0人学习

Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn