跳到主要内容

高级特性:装饰器(Decorator)


🧩 为什么需要装饰器?

在编程中,我们经常希望在不修改函数代码的前提下,为函数增加一些功能,比如:

  • 统计函数运行时间
  • 添加日志记录
  • 检查权限或参数
  • 缓存返回值...

这时候,就需要用到 装饰器(Decorator) —— 它能动态地“包装”一个函数,增强它的功能,而又不影响其原有的定义与调用。


🎁 装饰器的核心原理:函数是“第一类对象”

Python 中函数可以像变量一样传递、作为参数、返回值,因此可以定义“包装函数”。


✅ 装饰器的基础写法

装饰器(函数):
包装器():
打印("函数开始")
函数()
打印("函数结束")
返回 包装器

@装饰器
打招呼():
打印("你好,世界")

打招呼()

输出:

函数开始
你好,世界
函数结束

🎯 @装饰器名 等价于:

打招呼 = 装饰器(打招呼)

装饰器接收一个函数,并返回一个“新函数”替代原函数。


💡 带参数的装饰器

如果被装饰的函数有参数,该怎么处理呢?只需给包装器加参数即可。

装饰器(函数):
包装器(*参数, **关键词参数):
打印("调用前")
返回 函数(*参数, **关键词参数)
返回 包装器

@装饰器
加法(a, b):
返回 a + b

打印(加法(2, 3))

🎨 多层装饰器

可以叠加多个装饰器,最上面的先执行:

@装饰器A
@装饰器B
定 函数():
略过

等价于:

函数 = 装饰器A(装饰器B(函数))

🔧 实例:计算函数执行时间

导入 时间

时间统计(函数):
包装器(*参数, **关键词):
开始 = 时间.time()
结果 = 函数(*参数, **关键词)
结束 = 时间.time()
打印(f"耗时 {结束 - 开始:.2f} 秒")
返回 结果
返回 包装器

@时间统计
慢函数():
时间 导入 睡眠
睡眠(1)
打印("运行完毕")

慢函数()

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

functools 导入 

装饰者(函数):
@包(函数)
封装(*args, **kwargs):
返回 函数(*args, **kwargs)
返回 wrapper

不使用 wraps,原函数的名字、文档等会被覆盖。


✅ 小结

功能描述
@装饰器将函数传入另一个函数进行封装
可扩展可用于权限验证、日志、缓存等
可嵌套支持多层装饰
带参数*args, **kwargs 通用封装
保持函数元信息使用 @wraps

📘 下一章:上下文管理器和 with 语句 —— 自动资源管理的利器。

如需生成,请告诉我!