一、闭包,装饰器
# 一、闭包,装饰器
def w1():
def inner():
print('-------正在验证权限-----')
return inner
def f1():
print('--------f1---------')
# 1.执行w1(),此时return了inner函数,注意:目前w1函数里面的inner()函数不会被执行
# 2.innerFunc接受return值 所以实质innerFunc=inner 即innerFunc指向了inner
innerFunc = w1()
# 3.因为步骤2已经说明innerFunc指向了inner,innerFunc()就等于inner(), 所以这里打印-------正在验证权限-----
innerFunc()
# 那么需求来了,我想在inner函数中,执行f1()函数该怎么办呢?
def w1(func):
def inner():
print('-------正在验证权限-----')
func()
return inner
def f1():
print('--------f1---------')
# 1.执行w1(f1),调用函数w1,同时把f1的引用传给参数func, 所以此时inner函数中的func()相当于f1() 然后return
# 2.innerFunc接受return值inner
innerFunc = w1(f1)
# 3. innerFunc()就等于inner(), 而inner函数中除了有个print(),还有个func() 即f1()
# 所以此时会打印-------正在验证权限----- 和 --------f1---------
innerFunc()
# 这个时候问题又来了,我原来目的是为了调用f1函数的时候,自动调用w1里面的功能,现在多出来个innerFunc 岂不是违背了目的
# 那么我们知道执行w1(f1)后会return一个值,这个值我不用innerFunc接受, 我们用xxx, yyy, 随便你起名字 可以吗?
xxx = w1(f1)
xxx()
# 验证答案是可以的,那么既然能随便起名字,那我就起成f1,不就变成了f1(),这样我就在执行f1()的时候执行了w1中的内容
f1 = w1(f1)
f1()
# 上述的所有说明就是装饰器的原理,那么有没有简单的方式呢? 这时候知识点来了
def w1(func):
def inner():
print('-------正在验证权限-----')
func()
return inner
# 这一个@w1就等价于f1 = w1(f1)
@w1
def f1():
print('--------f1---------')
f1()
二、多个装饰器讨论
def w1(func):
def inner():
print('----正在执行w1-----')
func() # 相当于test1()
return inner
def w2(func):
def inner():
print('----正在执行w2-----')
func() # 相当于test()
return inner
@w1 # test = w1(test1)
@w2 # test1 = w2(test) test1指向了w2中的inner 此时inner中有 ----正在执行w2----- 和------test-------
def test():
print('------test-------')
test()
----正在执行w1-----
----正在执行w2-----
------test-------
解释:当程序自上而下进行到@w1时,发现@w1下面并不是一个函数,那么先不处理,继续往下走,走到@w2时,诶,发现了一个函数test,那么开始处理,由上面可知:test1指向了w2中的函数inner,那么此时inner中有----正在执行w2----- 和------test-------,接着w1(test1) 然后返回w1中的inner给test, 那么此时test里面就相当于有本身的----正在执行w1-----和test1指向的----正在执行w2----- 和------test-------。最后调用:test()
def w1(func):
print('-----正在装饰1----')
def inner():
print('----正在执行w1-----')
func()
return inner
def w2(func):
print('-----正在装饰2-----')
def inner():
print('----正在执行w2-----')
func()
return inner
@w1 # 只要python解释器执行到这部分代码,就会自动装饰,不会等调用才装饰
@w2
def test():
print('------test-------')
# test() 注意我屏蔽了调用
-----正在装饰2-----
-----正在装饰1----
解释:上面已经说到:发现@w1下面并不是一个函数,那么先不处理,所以先处理@w2,装饰@w2完后,再装饰@w1;同时要记住只要python解释器执行到这部分代码,就会自动装饰,不会等调用才装饰。
def w1(func):
print('-----正在装饰1----')
def inner():
print('----正在执行w1-----')
func()
return inner
def w2(func):
print('-----正在装饰2-----')
def inner():
print('----正在执行w2-----')
func()
return inner
@w1
@w2
def test():
print('------test-------')
-----正在装饰2-----
-----正在装饰1----
----正在执行w1-----
----正在执行w2-----
------test-------
总结:实在不清楚原理,可以简单理解为:装饰器哪个离函数近,就先装饰哪个, 执行就从上往下执行。
三、被装饰的函数有参数
def w1(func):
def inner(a, b): # 如果这里不写两个实参,那么调用test(1,2)会报错
print('-------')
func(a, b) # 如果这里不写两个实参,那么调用def test(a, b):会报错
return inner
@w1
def test(a, b):
print(a+b)
test(1,2)
# 不定长参数的装饰器
def w1(func):
def inner(*args, **kwargs):
print('-------')
func(*args, **kwargs)
return inner
@w1
def test(a, b, c):
print(a+b+c)
test(1,2,3)
四、装饰器装饰有返回值的函数
def w1(func):
def inner():
print('*****')
func()
return inner
@w1
def test():
print('----这是测试----')
return 'handsome'
test() # 打印结果可发现,并没有返回handsome
def w1(func):
def inner():
print('*****')
xxx = func() # 接收返回值handsome
return xxx # 这里写xxx是为了便于理解,有点不规范,所以最好写成ret
return inner
@w1
def test():
print('----这是测试----')
return 'handsome'
ret = test() # 调用函数的同时接收 return xxx 返回的结果
print(ret)
五、装饰器带参数
def w(arg):
def w1(func):
def inner():
print('------')
func()
print('arg的值是%s' % arg)
return inner
return w1
@w('wenwen')
def test():
print('----test------')
test()
解释:1.先执行 w('wenwen')这个函数,这个函数return的结果就是w1这个函数的引用
2.然后再@w1,使用@w1对test进行装饰