Python闭包与装饰器原理及实例解析
一、闭包
闭包相当于函数中,嵌套另一个函数,并返回。代码如下:
deffunc(name):#定义外层函数 definner_func(age):#内层函数 print('name:',name,',age:',age) returninner_func#注意此处要返回,才能体现闭包 bb=func('jayson')#将字符串传给func函数,返回inner_func并赋值给变量 bb(28)#通过变量调用func函数,传入参数,从而完成闭包 >> name:jayson,age:28
二、装饰器
装饰器:把函数test当成变量传入装饰函数deco-->执行了装饰操作后,变量传回给了函数test()。比如装饰器效果是test=test-1,test函数经过deco装饰后,调用test其实执行的是test=test-1。
1、装饰器是利用闭包原理,区别是装饰器在闭包中传入的参数是函数,而不是变量。
注:其实在装饰器中,函数即变量
defdeco(func):#传入func函数。 print('decoration') returnfunc deftest(): print('test_func') test=deco(test)#对函数进行装饰。执行了deco函数,并将返回值赋值给test >> #输出deco的运行结果 decoration test()#运行装饰后的函数 >> test_func
2、以上代码等价于
defdeco(func):#传入func函数。 print('decoration') returnfunc @deco#等价于上一代码中test=deco(test),不过上一代码需放在定义test之后 deftest(): print('test_func') >> #输出deco的运行结果 decoration test()#运行装饰后的函数 >> test_func
3、装饰器(简版)
defdeco(func):#装饰函数传入func print('decoration') returnfunc @deco#装饰函数。 deftest(): print('test_func') #定义完函数后,会直接执行装饰器deco(test) >> decoration #调用test,执行test函数 test() >> test_func
3、装饰器(升级版)
在上一个版本中,由于在定义装饰器+函数时,就会执行装饰函数里面的语句。
为了使其在未被调用时候不执行,需要再嵌套一个函数,将函数进行包裹。
defdeco(func): print('decoration')#此处未调用func函数时,会直接执行 defwrapper():#名称自定义,一般用wrapper print('execute')#此处未调用func函数时,不会执行 func()#执行函数 returnwrapper#此处返回wrapper给func,通过外部func()执行 @deco#注意:此处不能有括号。有括号的形式是func未传入最外层deco(),传入deco的子函数中 deftest(): print('test_func') >> decoration #调用test test() >> execute test_func
注意:如果func函数本身有返回值,同样需要在包裹函数中返回
defdeco(func): print('decoration') defwrapper(): print('execute') a=func()#执行函数,并返回值 print('done') returna#将func的返回值一并返回 returnwrapper @deco deftest(): print('test_func') return5#增加返回值 >> decoration #调用test test() >> execute test_func done #此处是test函数的返回值
3、装饰器(进阶版)
在包裹函数中,参数形式设置为*arg、**kwarg,会使得函数更加灵活。
当修改test函数参数形式时,不用在装饰器中同时修改。
importtime defdeco(func): definner(*arg,**kwarg):#此处传入参数 begin_time=time.time() time.sleep(2) a=func(*arg,**kwarg)#调用函数,使用传入的参数 end_time=time.time() print('运行时间:',end_time-begin_time) returna returninner @deco deftest(a): print('testfunction:',a) returna #调用函数 test(5) >> testfunction:5 运行时间:2.0003252029418945 #5是函数返回的值
4、高阶版
有时候我们会发现有的装饰器带括号,其原因是将上述的装饰器外面又套了一个函数
importtime defouter():#在原装饰器外套一层函数,将装饰器封装在函数里面。(outer自定义) defdeco(func):#原装饰器,后面的代码一样 definner(*arg,**kwarg): begin_time=time.time() time.sleep(2) a=func(*arg,**kwarg) end_time=time.time() print('运行时间:',end_time-begin_time) returna returninner returndeco#注意:此处需返回装饰函数 @outer()#此处就需要加括号,其实是调用了outer()函数,将test传进其子函数 deftest(a): print('testfunction:',a) returna test(4) >> testfunction:4 运行时间:2.000566005706787 #返回4
5、高阶终结版
带参数的装饰器(装饰器加括号,带参数)
importtime defouter(choose):#在最外层函数中加入参数 ifchoose==1:#通过choose参数,选择装饰器 defdeco(func): definner(*arg,**kwarg): print('decoration1') begin_time=time.time() time.sleep(2)#睡眠2s a=func(*arg,**kwarg) end_time=time.time() print('运行时间1:',end_time-begin_time) returna returninner returndeco else: defdeco(func): definner(*arg,**kwarg): print('decoration2') begin_time=time.time() time.sleep(5)#睡眠5s a=func(*arg,**kwarg) end_time=time.time() print('运行时间2:',end_time-begin_time) returna returninner returndeco @outer(1)#由于outer中有参数,此处必须传入参数 deftest1(a): print('testfunction1:',a) returna @outer(5)#传入另一个参数 deftest2(a): print('testfunction2:',a) returna #分别调用2个函数(2个函数装饰器相同,装饰器参数不同) test1(2)#调用test1 >> decoration1 testfunction1:2 运行时间1:2.000072717666626#2秒 #test1的返回值 test2(4)#调用test2 >> decoration2 testfunction2:4 运行时间2:5.000797986984253#5秒 #test2的返回值
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。