赞
踩
一、闭包,装饰器
- # 一、闭包,装饰器
-
- 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进行装饰
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。