【5.0】Python高级之装饰器
【一】什么是装饰器
装饰
代指为被装饰对象添加新的功能,器
代指器具/工具,装饰器与被装饰的对象均可以是任意可调用对象。- 概括地讲,装饰器的作用就是在不修改被装饰对象源代码和调用方式的前提下为被装饰对象添加额外的功能。
- 装饰器经常用于有切面需求的场景
- 插入日志、性能测试、事务处理、缓存、权限校验等应用场景
- 装饰器是解决这类问题的绝佳设计
- 有了装饰器,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。
提示:可调用对象有函数,方法或者类,此处我们单以本章主题函数为例,来介绍函数装饰器,并且被装饰的对象也是函数。
【二】装饰器的用途
- 软件的设计应该遵循开放封闭原则,即对扩展是开放的,而对修改是封闭的。
- 对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。
- 对修改封闭,意味着对象一旦设计完成,就可以独立完成其工作,而不要对其进行修改。
- 软件包含的所有功能的源代码以及调用方式,都应该避免修改,否则一旦改错,则极有可能产生连锁反应,最终导致程序崩溃
- 而对于上线后的软件,新需求或者变化又层出不穷,我们必须为程序提供扩展的可能性,这就用到了装饰器。
【三】装饰器的分类
- 函数装饰器分为:无参装饰器和有参装饰两种
- 二者的实现原理一样,都是’函数嵌套+闭包+函数对象’的组合使用的产物。
【四】无参装饰器
【1】引入
- 如果想为下述函数添加统计其执行时间的功能
【2】直接计时
- 遵循不修改被装饰对象源代码的原则,我们想到的解决方法可能是这样
【3】函数作为参数
- 考虑到还有可能要统计其他函数的执行时间
- 于是我们将其做成一个单独的工具,函数体需要外部传入被装饰的函数从而进行调用
- 我们可以使用参数的形式传入
- 但之后函数的调用方式都需要统一改成
- 这便违反了不能修改被装饰对象调用方式的原则
- 于是我们换一种为函数体传值的方式,即将值包给函数
【4】将值包给函数
- 这样我们便可以在不修改被装饰函数源代码和调用方式的前提下为其加上统计时间的功能
- 只不过需要事先执行一次timer将被装饰的函数传入,返回一个闭包函数wrapper重新赋值给变量名 /函数名index
- 至此我们便实现了一个无参装饰器timer,可以在不修改被装饰对象index源代码和调用方式的前提下为其加上新功能。
【5】问题:带参数会报错
- 但我们忽略了若被装饰的函数是一个有参函数,便会抛出异常
【6】无参装饰器模板
【五】有参装饰器
【1】有参装饰器详解
- 之所以会抛出异常,是因为home(egon)调用的其实是wrapper(egon),而函数wrapper没有参数。
- wrapper函数接收的参数其实是给最原始的func用的
- 为了能满足被装饰函数参数的所有情况,便用上*args+**kwargs组合
- 于是修正装饰器timer如下
【2】有参装饰器模版
【六】无参语法糖
【1】装饰器内函数无参语法糖
- 此时我们就可以用timer来装饰带参数或不带参数的函数了
- 但是为了简洁而优雅地使用装饰器,Python提供了专门的装饰器语法来取代index=timer(index)的形式
- 需要在被装饰对象的正上方单独一行添加
@timer
- 当解释器解释到
@timer
时就会调用timer函数 - 且把它正下方的函数名当做实参传入
- 然后将返回的结果重新赋值给原函数名
【2】装饰器内函数有参语法糖
【3】有参语法糖
【七】有参语法糖
【1】有参语法糖推导
- 了解无参装饰器的实现原理后
- 我们可以再实现一个用来为被装饰对象添加认证功能的装饰器
- 实现的基本形式如下
- 如果我们想提供多种不同的认证方式以供选择,单从wrapper函数的实现角度改写如下
- 函数wrapper需要一个driver参数,而函数deco与wrapper的参数都有其特定的功能
- 不能用来接受其他类别的参数,可以在deco的外部再包一层函数auth,用来专门接受额外的参数
- 这样便保证了在auth函数内无论多少层都可以引用到
【2】有参语法糖使用
- 此时我们就实现了一个有参装饰器,使用方式如下
【八】伪装装饰器
【1】查看装饰器(help)
- 可以使用help(函数名)来查看函数的文档注释,本质就是查看函数的doc属性
- 但对于被装饰之后的函数,查看文档注释
- 在被装饰之后home=wrapper
- 查看home.name也可以发现home的函数名确实是wrapper
- 想要保留原函数的文档和函数名属性,需要修正装饰器
【2】伪装装饰器(functools)
- 按照上述方式来实现保留原函数属性过于麻烦
- functools模块下提供一个装饰器wraps专门用来帮我们实现这件事
__EOF__

本文作者:Chimengmeng
本文链接:https://www.cnblogs.com/dream-ze/p/17843380.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/dream-ze/p/17843380.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文来自博客园,作者:Chimengmeng,转载请注明原文链接:https://www.cnblogs.com/dream-ze/p/17843380.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南