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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。