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、结束

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

相关推荐
码农飞哥10 分钟前
我把RAG召回率从60%提到90%,就改了这两件事
python·知识库·向量检索·rag·效果提示
宸津-代码粉碎机11 分钟前
Spring AI企业级实战|从RAG优化到Agent多工具调度
java·大数据·人工智能·后端·python·spring
yuhuofei202112 分钟前
【Python入门】Python中的字典dict
python
Jinkxs32 分钟前
Python基础 - 文件的写入操作 write与writelines方法
android·服务器·python
初学Python的小明39 分钟前
Python格式化输出、运算符、分支&循环
python
92year1 小时前
用 browser-use 让 AI 自己操作浏览器:从安装到自动填表全流程
python·ai·浏览器自动化·browser-use
财经资讯数据_灵砚智能1 小时前
基于全球经济类多源新闻的NLP情感分析与数据可视化(夜间-次晨)2026年6月6日
人工智能·python·ai·信息可视化·自然语言处理·ai编程·灵砚智能
千寻girling2 小时前
一周没跑步了 ,今日跑步 5KM , 哑铃+健身 20min , 俯卧撑 30 个 ;
数据结构·c++·python·算法·leetcode·职场和发展·线性回归
CTA量化套保2 小时前
Jupyter Notebook 反复运行天勤策略内存涨:close 与内核习惯
ide·人工智能·python·jupyter
kida_yuan2 小时前
不想花钱写了一个 Flask 知识库
运维·python