Python 装饰器,给你的函数加点“料”!
ztj100 2025-01-09 17:29 11 浏览 0 评论
各位程序猿、攻城狮们,大家好哇!今天咱们来聊聊 Python 里一个神奇的东东——装饰器 (Decorator)。 听到这个名字,是不是感觉有点高大上?别怕别怕,其实它就像我们给函数加个“魔法棒”,咻的一下,就能给函数“升级”一下,增加一些额外的功能,但又不用动它原本的代码,是不是很酷炫?
一、 开场白:你的函数需要“加点料”吗?
咱先来唠唠嗑。 你有没有遇到过这样的情况:
- 写了好几个函数,都需要在执行前后记录一下日志,难道要每个函数里都写一遍 print('开始执行...') 和 print('执行结束...') 吗?这也太 low 了吧!
- 有些敏感操作的函数,你想做个权限校验,只有特定用户才能调用,难道要挨个函数里面写 if user.is_admin: 吗?这也太麻烦了吧!
- 你想统计一下某个函数的运行时间,看看是不是“老牛拉破车”,难道又要改动函数内部的代码,加个计时器?这…谁愿意干啊!
每当遇到这些 “重复劳动” 的时候,我的内心 OS 都是:有没有什么“一劳永逸”的办法,能给这些函数“批量加buff”呢?
嘿嘿,告诉你,还真有!Python 的装饰器就是干这个的!它就像一个“函数调料包”,你想给哪个函数“加点料”,就往它身上“撒”一点,简单粗暴又有效!
二、 装饰器是啥玩意?别光说不练啊!
说了这么多,装饰器到底是个啥呢?别急,咱们先看个简单的例子:
def my_decorator(func):
def wrapper():
print("函数执行前,我在加点料!")
func()
print("函数执行后,我也没闲着!")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
运行一下,看看会输出啥?
函数执行前,我在加点料!
Hello!
函数执行后,我也没闲着!
是不是有点意思了? say_hello 函数原本只是打印 "Hello!",但是经过 @my_decorator 这么一“装饰”,就多了两行额外的输出。
敲黑板,划重点啦!
- 装饰器本质上是一个 Python 函数 (如上面的 my_decorator)。
- 它可以接收一个函数作为参数 (如上面的 say_hello)。
- 它会返回一个新的函数 (如上面的 wrapper)。
- @my_decorator 这种写法,其实就是个“语法糖”,相当于 say_hello = my_decorator(say_hello)。 是不是感觉一下子就 get 到了?
你可以把装饰器想象成一个“包装纸”,你把原来的函数(比如一个礼物)放进去,经过装饰器这么一“包装”,就变成了一个“加了额外功能”的新礼物。
三、 装饰器的工作原理:幕后的小秘密
咱们再来扒一扒装饰器背后的“小秘密”。 当你用 @my_decorator 装饰 say_hello 的时候,Python 实际上做了这么几件事:
- 它把 say_hello 这个函数当作参数,传给了 my_decorator 函数。
- my_decorator 函数内部定义了一个新的函数 wrapper,在这个 wrapper 函数里,你可以做一些“加料”的操作(比如打印日志),然后调用原来的 func 函数。
- my_decorator 函数最后返回了这个新的 wrapper 函数。
- 最终,say_hello 这个名字不再指向原来的函数了,而是指向了 my_decorator 返回的那个 wrapper 函数。
所以,当你调用 say_hello() 的时候,实际上是在执行 wrapper() 函数里面的代码。 是不是感觉瞬间高大上了起来?
四、 装饰器的各种姿势:不止一种玩法!
上面的例子是最简单的装饰器,但装饰器可不止这一种玩法哦!
1. 带参数的装饰器:更灵活的“调料包”
有时候,我们希望装饰器也能接收一些参数,让它可以更灵活地“加料”。 比如,我们想让日志信息可以自定义:
def log(text):
def decorator(func):
def wrapper(*args, **kwargs):
print(f"[{text}] {func.__name__} 函数开始执行啦!")
result = func(*args, **kwargs)
print(f"[{text}] {func.__name__} 函数执行完毕!")
return result
return wrapper
return decorator
@log('DEBUG')
def my_function(name):
print(f"Hello, {name}!")
my_function("Alice")
输出结果:
[DEBUG] my_function 函数开始执行啦!
Hello, Alice!
[DEBUG] my_function 函数执行完毕!
注意看! @log('DEBUG') 这种写法,其实相当于 my_function = log('DEBUG')(my_function)。 log('DEBUG') 会先执行,返回一个装饰器函数,然后再用这个返回的装饰器函数去装饰 my_function。 是不是有点绕?多看几遍就明白了!
2. 装饰器装饰带参数的函数:雨露均沾
上面的例子里,被装饰的函数 say_hello 和 my_function 分别是没有参数和有一个参数的情况。 如果被装饰的函数有多个参数,我们该怎么办呢?
在 wrapper 函数里使用 *args 和 **kwargs 就能完美解决! *args 用来接收所有位置参数,**kwargs 用来接收所有关键字参数,保证“雨露均沾”,不会漏掉任何一个参数。
3. 类装饰器:让装饰器也“面向对象”
除了用函数来做装饰器,我们还可以用类来实现装饰器。 只需要在类里面实现 __call__ 方法,这个类的实例就可以像函数一样被调用,也就可以作为装饰器来使用了。
class Counter:
def __init__(self, func):
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"函数 {self.func.__name__} 第 {self.count} 次被调用!")
return self.func(*args, **kwargs)
@Counter
def my_action():
print("执行了一个动作!")
my_action()
my_action()
输出结果:
函数 my_action 第 1 次被调用!
执行了一个动作!
函数 my_action 第 2 次被调用!
执行了一个动作!
类装饰器通常用于维护一些状态信息,比如上面的计数器。
五、 装饰器的应用场景:哪里需要哪里搬!
装饰器在实际开发中可是非常实用的 “小能手”! 来看看它都能帮我们做些什么:
- 日志记录: 统一记录函数的调用信息、参数、返回值等。
- 性能监控: 统计函数的运行时间,找出性能瓶颈。
- 权限校验: 检查用户是否有权限调用某个函数。
- 缓存: 缓存函数的计算结果,避免重复计算。
- 事务处理: 在函数执行前后开启和提交/回滚事务。
- 路由控制 (Web 框架): 将 URL 映射到对应的处理函数。
可以说,只要你想在不修改原函数代码的情况下,给函数增加一些额外的功能,装饰器都能派上用场!
六、 总结一下:给你的技能树点亮新技能!
好啦,今天关于 Python 装饰器的讲解就到这里啦! 希望通过这篇轻松幽默的文章,让你对装饰器有了更深入的理解。 记住,装饰器其实并没有那么可怕,它只是 Python 提供的一个强大的 “语法糖”,能让你的代码更加简洁、优雅、易于维护。
最后,留个小思考题: 如果一个函数被多个装饰器装饰,它们的执行顺序是怎样的呢? 欢迎在评论区留言讨论!
下一篇,咱们可以聊聊 Python 的生成器和迭代器,也是 Python 中非常重要的概念哦! 敬请期待! 溜啦溜啦~
相关推荐
- Whoosh,纯python编写轻量级搜索工具
-
引言在许多应用程序中,搜索功能是至关重要的。Whoosh是一个纯Python编写的轻量级搜索引擎库,可以帮助我们快速构建搜索功能。无论是在网站、博客还是本地应用程序中,Whoosh都能提供高效的全文搜...
- 如何用Python实现二分搜索算法(python二分法查找代码)
-
如何用Python实现二分搜索算法二分搜索(BinarySearch)是一种高效的查找算法,适用于在有序数组中快速定位目标值。其核心思想是通过不断缩小搜索范围,每次将问题规模减半,时间复杂度为(O...
- 路径扫描 -- dirsearch(路径查找器怎么使用)
-
外表干净是尊重别人,内心干净是尊重自己,干净,在今天这个时代,应该是一种极高的赞美和珍贵。。。----网易云热评一、软件介绍Dirsearch是一种命令行工具,可以强制获取web服务器中的目录和文件...
- 78行Python代码帮你复现微信撤回消息!
-
来源:悟空智能科技本文约700字,建议阅读5分钟。本文基于python的微信开源库itchat,教你如何收集私聊撤回的信息。...
- 从零开始学习 Python!2《进阶知识》 Python进阶之路
-
欢迎来到Python学习的进阶篇章!如果你说已经掌握了基础语法,那么这篇就是你开启高手之路的大门。我们将一起探讨面向对象编程...
- 白帽黑客如何通过dirsearch脚本工具扫描和收集网站敏感文件
-
一、背景介绍...
- Python之txt数据预定替换word预定义定位标记生成word报告(四)
-
续接Python之txt数据预定替换word预定义定位标记生成word报告(一)https://mp.toutiao.com/profile_v4/graphic/preview?pgc_id=748...
- Python——字符串和正则表达式中的反斜杠('\')问题详解
-
在本篇文章里小编给大家整理的是关于Python字符串和正则表达式中的反斜杠('\')问题以及相关知识点,有需要的朋友们可以学习下。在Python普通字符串中在Python中,我们用'\'来转义某些普通...
- Python re模块:正则表达式综合指南
-
Python...
- python之re模块(python re模块sub)
-
re模块一.re模块的介绍1.什么是正则表达式"定义:正则表达式是一种对字符和特殊字符操作的一种逻辑公式,从特定的字符中,用正则表达字符来过滤的逻辑。(也是一种文本模式;)2、正则表达式可以帮助我们...
- MySQL、PostgreSQL、SQL Server 数据库导入导出实操全解
-
在数字化时代,数据是关键资产,数据库的导入导出操作则是连接数据与应用场景的桥梁。以下是常见数据库导入导出的实用方法及代码,包含更多细节和特殊情况处理,助你应对各种实际场景。一、MySQL数据库...
- Zabbix监控系统系列之六:监控 mysql
-
zabbix监控mysql1、监控规划在创建监控项之前要尽量考虑清楚要监控什么,怎么监控,监控数据如何存储,监控数据如何展现,如何处理报警等。要进行监控的系统规划需要对Zabbix很了解,这里只是...
- mysql系列之一文详解Navicat工具的使用(二)
-
本章内容是系列内容的第二部分,主要介绍Navicat工具的使用。若查看第一部分请见:...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- Whoosh,纯python编写轻量级搜索工具
- 如何用Python实现二分搜索算法(python二分法查找代码)
- 路径扫描 -- dirsearch(路径查找器怎么使用)
- 78行Python代码帮你复现微信撤回消息!
- 从零开始学习 Python!2《进阶知识》 Python进阶之路
- 白帽黑客如何通过dirsearch脚本工具扫描和收集网站敏感文件
- Python之txt数据预定替换word预定义定位标记生成word报告(四)
- 假期苦短,我用Python!这有个自动回复拜年信息的小程序
- Python——字符串和正则表达式中的反斜杠('\')问题详解
- Python re模块:正则表达式综合指南
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- node卸载 (33)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- exceptionininitializererror (33)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)