




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第Python的@装饰器的作用小结我们在编程过程中,常常会遇到这种需求:
比如,我想开发一款计算器,我已经写好了一堆函数,用于执行各种计算,那么我们需要在执行各种计算函数前,首先对输入的数据进行检查,确保他们必须得是数值才允许执行函数,而不能是字符串;
又如,我想编写一个用于计算三角形周长、面积、某个角角度的模块,已经写好几个函数用于计算,那么,在执行计算前,首先要确保输入的三条边长能够构成三角形,再进行计算才有意义;
再比如,我想开发某款网络应用,写了一些函数用于实现用户的某些操作,那么,得要先检查确认该用户已经登录了,才允许执行这些操作。
这些需求,归纳起来,就是,在执行主函数之前,常常要先执行某个预函数,进行一些校验之类的操作。
这类需求是非常常见的,也是保证程序完整性、健壮性的重要举措。所以,怎么做才比较简单呢?
你会说,这很简单啊,在每个函数里面写上if语句不就得了。就拿那个计算器而言,如果我们要写加减乘除,我们可以这样:
defplus(a,b):
iftype(a)==type(0)andtype(b)==type(0):#假设该计算器只能计算整数,如果要计算小数再ortype(0.0)
returna+b
else:
print('Typemustbenumber')#检测到数据类型不对,先输出报警,函数值返回None
returnNone
defminus(a,b):
iftype(a)==type(0)andtype(b)==type(0):
returna-b
else:
print('Typemustbenumber')
returnNone
defmultiply(a,b):
iftype(a)==type(0)andtype(b)==type(0):
returna*b
else:
print('Typemustbenumber')
returnNone
defdivide(a,b):
iftype(a)==type(0)andtype(b)==type(0):
returna/b
else:
print('Typemustbenumber')
returnNone
这个嘛,直接暴力。但是呢,这里只有4个函数,假如你开发的计算器有几十几百个函数,每个函数都要套上if语句,这不得麻烦死了,不烦死也啰嗦死了。
所以怎么弄简单一点呢?聪明的你肯定想到了,我们可以把那个判断if也单独定义一个函数,然后把计算用的函数套在里面,就像这样:
defcheck(a,b,func):#定义检查函数,变量为待检测参数a,b和检测通过后执行的函数func
iftype(a)==type(0)andtype(b)==type(0):
returnfunc(a,b)
else:
print('Typemustbenumber')
returnNone
defplus(a,b):
returna+b
defminus(a,b):
returna-b
check(1,2,plus)#计算1+2
check(1,2,minus)#计算1-2
check(1,2,multiply)#计算1*2
check(1,2,divide)#计算1/2
这里面有一点一定要特别注意,主程序的check(1,2,plus)是把plus函数本身作为变量传递给check,由check函数决定如何执行plus函数,此处不能写成check(1,2,plus(1,2)),plus不能带参数和括号,不是执行plus()后把结果传给check。
这么写程序简洁了不少,加减乘除函数只需要定义他们本身的运算就可以了,变量检测交给了check函数。这么写也是比较容易理解的。
但是对于使用该程序的用户来说,就不是这么回事了,他们会觉得这么写非常难看。
为什么呢?我是要拿程序做加减乘除计算的,但我不论计算什么,每次都是在主调用check这个函数!
那有没有什么办法,可以既好看,又简洁呢?装饰器就是起到了这个神奇的作用。
上面这个需求,用装饰器可以这么写:
defcheck(func):
@check
defplus(a,b):
returna+b
@check
defminus(a,b):
returna-b
plus(1,2)#计算1+2
minus(1,2)#计算1-2
先直观感受一下,通过@check,check函数就被“注入”到了plus函数中,使得plus函数拥有了参数检测的功能。这样,在主程序中,若要计算加法就可直接调用plus,便可先校验再计算。
那么,这个装饰器check要怎么定义呢?我们来看一下。
defcheck(func):#定义装饰器check
defnewfunc(a,b):#定义函数模板,即如何处理func
iftype(a)==type(0)andtype(b)==type(0):
returnfunc(a,b)
else:
print('Typemustbenumber!')
returnNone
returnnewfunc#将处理后的func作为新函数newfunc输出
@check
defplus(a,b):
returna+b
#主程序,计算1+2
plus(1,2)
我们可以看到,当装饰器@check作用于plus函数时,plus函数本身作为参数func传入装饰器中。在装饰器check的定义内部,定义了一个函数模板,描述了对输入的func如何处理。可以看到,newfunc对func(也就是输入的plus)套用了判断数据类型的if语句,最后,再将套好的newfunc输出,替代原来的func。这样,此时执行func就是在执行newfunc,执行plus就是在执行套上if语句的新函数。
所以,通过装饰器,添加上了判断语句的新函数替换了原来的plus函数,但仍通过plus这个函数名调用,所以看起来就是plus函数被“装饰”了。
当然了,如果大家在网络上搜索,关于如何定义装饰器,看到的是一个更加规范的版本。看起来更难理解一些,但其实是一样的:
defcheckall(func):
defwrapper(*args,**kwargs):
iftype(args[0])==type(0)andtype(args[1])==type(0):
returnfunc(*args,**kwargs)
else:
print('Typemustbenumber!')
returnNone
returnwrapper
模板函数一般习惯用wrapper来表示,这个没啥,建议大家都这么写,规范一些。
参数一般用不定长的*args,**kwargs来表示,这个可能有些人就困惑了。因为被装饰的函数可能有很多种,参数的个数一般也不确定。然后*args,**kwargs是什么东西?args,kwargs这两个形参英文字母是什么无所谓可以自己定,关键是前面的单星号*和双星号**。
假如我定义一个函数,不能确定参数有多少个,例如要对输入的一组数字做连加操作。那么就可以定义plus(*x),当调用该函数时,若输入多个变量plus(1,2,3),那么就会把输入的变量组合成一个元祖x=(1,2,3)输入。定义双星号plus(**x)的意思是,调用该函数时若写出形参变量plus(a=1,b=2,c=3),那么输入变量就会组合成字典x={a:1,b:2,c:3}传入函数。
当然也可以反向操作,定义函数的时候参数个数是明确的plus(a,b,c),那么调用该函数时,加上星号plus(*(1,2,3)),就是对输入元祖(1,2,3)执行炸开操作,转换为plus(1,2,3)输入。
装饰器里这么写有什么用呢?我们仔细观察一下我们之前写的newfunc(a,b),那就意味着,指明了新函数有两个参数a,b,假如被装饰的原函数有三个参数怎么办呢?不就没用了吗?
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 代谢笼租赁服务及实验动物饲养管理协议
- 电商店铺装修设计及供应链管理合作协议
- 跨境知识产权忠诚协议资产冻结与知识产权保护协议
- 房屋相邻权与物业管理服务合同
- 网络广告技术服务补充协议
- 智能家居网关设备研发与市场推广服务合同
- 专属私人飞机航线申请与VIP接送合同
- 员工股权解锁与公司融资协议
- 生物检测试剂盒市场推广及销售合作合同
- 现代化工企业生产管理体系建设
- 大学文化主题辩论赛巅峰对决辩论辩答ppt模板
- c型钢理论重量表规格表
- 广东旅游车队公司一览
- ESD标准培训资料ppt课件
- 河南省确山县三里河治理工程
- 水利工程合同工程完工验收工程建设管理工作报告
- 多级泵检修及维护(1)
- 涵洞孔径计算
- 测量未知电阻的方法
- 中国民主同盟入盟申请表
- 观感质量检查表
评论
0/150
提交评论