理解 Python 中的装饰器
前言
装饰器是Python中的一个重要概念,多用于在不修改原函数的基础上,为函数增加额外的功能。
基础装饰器
例如小李给女朋友买了一款iPhone12作为生日礼物,手机原封未拆封。
def gift():print('iPhone12')gift() # 运行显示礼物信息
但还是觉得礼物太单薄,于是又买了一盒德芙巧克力,一支dior的口红,并找了个精美的礼品盒包装了一下,盒子里放满了泡沫球。
def gift():print('iPhone12')def box(gift):print('='*5 + '礼物盒' + '='*5)print('一盒泡沫球')print('好多巧克力')print('一支dior口红')return giftgift = box(gift) # 将礼物包装后作为礼物
gift() # 显示礼物信息
运行后显示如下:
=====礼物盒=====
一盒泡沫球
好多巧克力
一支dior口红
iPhone12
这个box便是一个装饰器,它的参数是一个函数对象,同数字、字符串、列表、字典等数据类型一样,函数和类也可以作为函数的参数使用,毕竟在Python里人人平等,一切皆对象。
box在使用时依然返回了原来的gift,只是在拿到这个gift之前增加了两个额外的惊喜,然后我们把box作为gift使用即可。
装饰器本质上就是以函数作为参数,对函数做一些处理,并替换原函数的一种高阶函数。
上例中,使用装饰器表示为如下。
def box(gift): # 以函数为参数的装饰器print('='*5 + '礼物盒' + '='*5)print('一盒泡沫球')print('好多巧克力')print('一支dior口红')return gift@box # 挂载装饰器,会自动替换原函数
def gift():print('iPhone12')gift() # 这里面得到的gift实际上是装饰后的gift即`box(gift)`
运行后显示和上例相同。
处理函数参数
小李突然想到,买哪个颜色应该征询下女友的意见,也就是原来的gift应支持一个可供选择的颜色参数。
def gift(color):print(f'iPhone12{color}版')
作为一个细心的boyfriend,小李需要根据对应的手机颜色选择同样颜色的泡沫球,也就是需要能获取到,被装饰的gift函数的参数。
这时候我们需要在盒子内部(box装饰器),重新准备一个新的礼物,根据颜色参数做不同的处理,然后根据颜色拿到指定的iPhone12礼物。
def box(gift):print('='*5 + '礼物盒' + '='*5)def new_gift(color): # 准备一个新的礼物,参数和原gift参数一致print(f'一盒{color}泡沫球') # 根据颜色准备泡沫球print('好多巧克力')print('一支dior口红')return gift(color) # 根据颜色拿到指定的iPhone12return new_gift # 返回新礼物,新礼物调用时,增加一些惊喜,并返回原有礼物gift(color)的结果。@box
def gift(color):print(f'iPhone12{color}版')gift('红色') # 实际上这里的gift是被box装饰后狸猫换太子的new_gift函数,而new_gift('红色'),返回原gift('红色')的结果。
在box内部为了根据参数做对应处理,我们新建了一个函数,函数内部也可以定义内部函数,内部函数new_gift可以获取并使用外部box函数的参数,如gift。
为了能获取到原有函数gift的参数,我们需要建立一个傀儡函数new_gift,这个函数和原函数gift的参数一致、返回结果一致,即new_gift(‘红色’)返回的就是gift(‘红色’)。
然后狸猫换太子,不再返回原来的gift函数对象,而是返回替换的new_gift函数对象。
运行后显示
=====礼物盒=====
一盒红色泡沫球
好多巧克力
一支dior口红
iPhone12红色版
注意:在装饰器box里,要返回一个函数对象,如上例中的return gift或本例中的return new_gift。而在傀儡函数new_gift中,为了和原函数gift结果一致,要返回原函数的调用结果即gift(color)。
从普遍意义上讲,作为商家,为了装饰器box可以包装任何形式的礼物,无论礼物有什么参数都可以满足,这就要求我们的傀儡函数new_gift支持任意类型的参数即def new_gift(args, **kwargs)。
然后把无论什么参数args, **kwargs交由原函数gift(*args, **kwargs)处理即可。
修改后,我们便得到一个通用的装饰器,可以包装任何礼物。
def box(gift):print('='*5 + '礼物盒' + '='*5)def new_gift(*args, **kwargs): # 接受任意数量的参数if args and len(args) > 0: # 由于参数不确定了,我们假设万一有参数,第一个参数是color参数color = args[0]print(f'一盒{color}泡沫球')else:print(f'一盒泡沫球')print('好多巧克力')print('一支dior口红')result = gift(*args, **kwargs) # 如果我们需要对原函数的结果做出处理,可以先获取到结果# print(f'原函数结果{result}') 由于原函数gift没有return,这是其实是Nonereturn result # 返回原函数结果return new_gift @box
def gift(color, pro=False): # 新的礼物函数,两个参数,默认买12,万一女友要Pro,也可以if pro is True:print(f'iPhone12 Pro{color}版')else:print(f'iPhone12{color}版')gift('海蓝色', pro=True)
这样,无论被装饰的函数有几个参数,box装饰器都可以正常处理。
运行后显示如下。
=====礼物盒=====
一盒海蓝色泡沫球
好多巧克力
一支dior口红
iPhone12 Pro海蓝色版
带参装饰器
信心满满的小李觉得,在盒子上还可以做些文章,要根据女友的喜好选择不同形状的箱子,因此我们需要根据参数来定制我们的装饰器box,在盒子外面再加一层定制函数。
def custom_box(shape): # 根据参数定制装饰器def box(gift): # 装饰器函数print('='*5 + f'{shape}礼物盒' + '='*5) # 根据形状定制# ...return box # 返回装饰器函数
此时我们得到一个可以根据参数进行定制的装饰器函数custom_box,这个装饰器接收到参数后,传递给真实装饰器box,并返回定制后box装饰器函数。
完整代码如下。
def custom_box(shape): # 根据参数定制装饰器 =====================def box(gift): # 实际的装饰器函数 ---------------------------print('='*5 + f'{shape}礼物盒' + '='*5)def new_gift(*args, **kwargs): # 傀儡函数 ..............if args and len(args) > 0:color = args[0]print(f'一盒{color}泡沫球')else:print(f'一盒泡沫球')print('好多巧克力')print('一支dior口红')result = gift(*args, **kwargs)return result # 返回原函数结果 ......................return new_gift # 返回傀儡函数 ---------------------------return box # 返回定制的装饰器 ===============================@custom_box('心形') # 使用可定制的装饰器
def gift(color, pro=False): if pro is True:print(f'iPhone12 Pro{color}版')else:print(f'iPhone12{color}版')gift('海蓝色', pro=True)
注意:装饰器在导入模块时立即计算的,即没调用gift(‘海蓝色’, pro=True)之前就已经执行生成定制后的box。
运行后,结果如下。
=====心形礼物盒=====
一盒海蓝色泡沫球
好多巧克力
一支dior口红
iPhone12 Pro海蓝色版
理解 Python 中的装饰器相关推荐
- [转载]理解PYTHON中的装饰器
[翻译]理解PYTHON中的装饰器 来源stackoverflow上的问题 链接 python的函数是对象 要理解装饰器,首先,你必须明白,在python中,函数是对象. 这很重要. 简单例子来理解为 ...
- python装饰器作用-理解python中的装饰器
一 什么是装饰器? 正如其名,装饰器的作用是为已经存在的对象增加额外功能(装饰),由此可使已有函数在无需代码改动的情况下增加额外功能:装饰器的本质是嵌套的函数且返回函数对象,即闭包.有关闭包的概念,可 ...
- python装饰器原理-python 中的装饰器及其原理
装饰器模式 此前的文章中我们介绍过装饰器模式: 装饰器模式中具体的 Decorator 实现类通过将对组建的请求转发给被装饰的对象,并在转发前后执行一些额外的动作来修改原有的部分行为,实现增强 Com ...
- 为什么说想到Python中的装饰器是天才
为什么说想到Python中的装饰器是天才 只需一个@符号就能分析.测试和重复使用你的代码 带着魔杖的仙女在Python代码中飞舞 软件中有没有什么是神奇的小魔法? 有,装饰器却非常接近! 如果说有一件 ...
- python类装饰器详解-python 中的装饰器详解
装饰器 闭包 闭包简单的来说就是一个函数,在该函数内部再定义一个函数,并且这个内部函数用到了外部变量(即是外部函数的参数),最终这个函数返回内部函数的引用,这就是闭包. def decorator(p ...
- python中的装饰器decorator
python中的装饰器 装饰器是为了解决以下描述的问题而产生的方法 我们在已有的函数代码的基础上,想要动态的为这个函数增加功能而又不改变原函数的代码 例如有三个函数: def f1(x):return ...
- python编写装饰器_写python中的装饰器
python中的装饰器主要用于在已有函数实现功能前附加需要输出的信息,下面将用实例展示我如何写装饰器. 首先分别尝试写装饰器装饰一个无参函数和一个有参函数(被装饰函数仅输出,无返回值情况下) 1 de ...
- python中的装饰器(基础装饰器)
文章目录 一 前置知识-高阶函数,闭包 1. 高阶函数 2. 闭包 二 函数装饰器 1. 什么是装饰器(原理)? 2. 装饰器的实现 3. 何时执行装饰器 4. wraps方法 三 类装饰器 一 前置 ...
- python中的装饰器有哪些-python 装饰器以及开发中常用的例子
有时候我们想为多个函数,同意添加某一种功能,比如及时统计,记录日志,缓存运算结果等等,而又不想改变函数代码 那就定义装饰器函数,用它来生成一个在原函数基础添加了新功能的函数,代替原函数 参考金角大王的 ...
最新文章
- 域用户绑定计算机批量设置,Windows 2008 AD域账户与计算机名批量绑定
- Normalize.css :一种用于重置默认的CSS样式的样式工具
- SQL工作笔记-达梦7中存储过程相关笔记(有参、无参、变量声明)
- vue中的静态资源打包
- 达梦数据库查询表结构
- 数学第一单元计算机思维导图,七年级下册数学第一单元思维导图
- C语言段错误-core文件
- scratch python的区别ev3_机器人编程和少儿编程,傻傻分不清—乐高EV3入门感想
- 2节串联锂电池充电管理IC芯片,5V,12V升降压解决方案
- 收藏 | 江苏省各地教师公务员等实际工资爆料
- 服务器cpu开启虚拟化的好处,开启硬件虚拟化有什么好处和坏处?
- 微信登录+sdk+服务器,微信sdk后端集成
- 现网必用的主备冗余技术,VRRP理论+配置
- 《墨宝非宝经典作品合集(套装共10册)》墨宝非宝(作者)epub+mobi+azw3格式下载...
- 睡眠伤害计算机硬件吗,电脑长时间睡眠、不关机对电脑有伤害吗?
- 百度智能云 API鉴权总结
- Windows10+ubuntu 双系统安装(针对联想小新air14)
- 【ACWing】1063. 永无乡
- 管理信息系统期末复习资料
- 第三章 事件 windows程序设计 王艳平版