Python的装饰器

装饰器是什么?在Python中,装饰器是使用'@'语法糖的修饰函数的语句,一般出现在函数定义的上方。装饰器的作用是增强被修饰函数的功能,譬如给函数增加日志功能等。

如何实现装饰器?有两种实现方式,一是基于闭包实现,闭包的概念参考Python中的闭包 - 掘金 (juejin.cn),而是基于类实现,两种方式中,闭包的方式相对简单,我们重点看下基于闭包的装饰器。

1、无参装饰器

打开Pycharm,我们先实现一个简单的闭包,并定义一个普通函数print_info:

在上面代码中,outer_func中嵌套了inner_func的定义,传递func参数,并返回inner_func引用;inner_func定义中,实现了一行打印,并调用了func。普通函数print_info实现了简单打印,仅作演示用。

通常情况下,我们会使用如下方式来用闭包去管理普通函数:

print_info作为参数,调用outer_func得到p,然后p就相当于print_info了,可以正常调用,运行一下:

但是这种方式比较繁琐,而且不够优雅,需要写很多闭包管理语句,因此Python提供了'@'语法糖:

在被修饰函数上面,使用'@装饰器'修饰被修饰函数,然后直接使用print_info即可:

运行结果与不使用'@'语法时一样,但是后者更加简洁和优雅。

实际上,可以简单理解使用'@'语法后的行为:

ini 复制代码
print_info = outer_func(print_info)

这个时候的print_info被修改了,实际上变成了闭包函数,普通函数可以直接使用。

2、有参装饰器

上节的无参装饰器是最简单的,实际应用中可能会需要使用有参装饰器。举个栗子,软件的日志系统通常会分日志级别,比如"debug"、"info"、"warn"、"error"、"fatal"等,如果我们的需求是,不同函数输出不同的日志级别,这个时候使用无参装饰器就无法完成了,必须使用有参装饰器,将日志级别信息通过装饰器传递过去。

在无参装饰器中,两层嵌套函数即可实现无参装饰器,那要实现有参装饰器需要在两层嵌套函数中再增加一层函数定义,形成三层嵌套函数,具体演示如下:

在outger_func定义之外增加了log函数定义,在log函数中,传递日志级别level,并返回outer_func定义。同时,在inner_func中,把level给打印出来了。好了,使用这个三层嵌套函数形成的闭包来修饰下print_info:

可以看到装饰器可以传递参数了,运行一下:

日志级别被正确传递给闭包了。

同无参装饰器一样,可以简单理解有参装饰器使用'@'语法后的行为:

ini 复制代码
print_info = log('debug')(print_info)

所以'@'后会紧跟闭包定义中最近外层函数的引用,并自动完成上述转换。

3、基于类的装饰器

前两节中的装饰器都是基于闭包的,事实上,闭包很多特性,面向对象中也是具备的,因此基于类也可以实现装饰器。基于类的装饰器没有闭包实现方便,这里不作深入分析,仅作示例:

这里补充下,基于类的装饰器是利用魔术方法__call__,这个方法可以类像函数一样执行,效果如下:

markdown 复制代码
# 拥有__call__方法的类
对象 = 类() # 实例化,调用__init__
对象() # 调用__call__方法

4、结束

实际上,装饰器一般出现在大型项目中,譬如大型框架,小型项目通常可以选用。基于函数(闭包)和基于类均可实现装饰器,推荐闭包模式的装饰器,简单易用。

相关推荐
想会飞的蒲公英2 小时前
计算机怎样读取中文文本:编码、清洗与标准化
人工智能·python·自然语言处理
SeaTunnel3 小时前
从 Python Script 地狱到标准化数据集成框架
大数据·开发语言·python·程序员·代码·seatunnel
深度研习笔记3 小时前
OpenCV工业视觉实战09|项目EXE打包+工控机无环境部署+后台常驻运行,彻底脱离Python环境,完成项目最终交付
python·opencv·webpack
CCPC不拿奖不改名3 小时前
大模型推理架构与开源生态知识整理
数据库·windows·python·架构·langchain·开源·github
Marst Code4 小时前
(python)2026Plotly 库评估:交互式可视化到底值不值得引入?
开发语言·python
databook4 小时前
当散点图不够用时:用 t-SNE 可视化多维数据
python·数据分析·数据可视化
我的xiaodoujiao6 小时前
快速学习Python基础知识详细图文教程9--函数进阶
开发语言·python·学习·测试工具
weixin_408099677 小时前
2026 图片去水印 API 接口完全指南:一键去除图片水印(附 Python/Java/PHP/C# 示例)
java·python·php·图片处理·api调用·图片去水印·石榴智能
去码头整点薯条ing7 小时前
某当网登录滑块【协议+OCR】
爬虫·python·ocr
赶紧写完去睡觉8 小时前
Anaconda 创建虚拟环境与使用
python·pycharm·conda