当前位置:   article > 正文

简单讨论装饰器_print(正在装饰)

print(正在装饰)

一、闭包,装饰器 

  1. # 一、闭包,装饰器
  2. def w1():
  3. def inner():
  4. print('-------正在验证权限-----')
  5. return inner
  6. def f1():
  7. print('--------f1---------')
  8. # 1.执行w1(),此时return了inner函数,注意:目前w1函数里面的inner()函数不会被执行
  9. # 2.innerFunc接受return值 所以实质innerFunc=inner 即innerFunc指向了inner
  10. innerFunc = w1()
  11. # 3.因为步骤2已经说明innerFunc指向了inner,innerFunc()就等于inner(), 所以这里打印-------正在验证权限-----
  12. innerFunc()
  13. # 那么需求来了,我想在inner函数中,执行f1()函数该怎么办呢?
  14. def w1(func):
  15. def inner():
  16. print('-------正在验证权限-----')
  17. func()
  18. return inner
  19. def f1():
  20. print('--------f1---------')
  21. # 1.执行w1(f1),调用函数w1,同时把f1的引用传给参数func, 所以此时inner函数中的func()相当于f1() 然后return
  22. # 2.innerFunc接受return值inner
  23. innerFunc = w1(f1)
  24. # 3. innerFunc()就等于inner(), 而inner函数中除了有个print(),还有个func() 即f1()
  25. # 所以此时会打印-------正在验证权限----- 和 --------f1---------
  26. innerFunc()
  27. # 这个时候问题又来了,我原来目的是为了调用f1函数的时候,自动调用w1里面的功能,现在多出来个innerFunc 岂不是违背了目的
  28. # 那么我们知道执行w1(f1)后会return一个值,这个值我不用innerFunc接受, 我们用xxx, yyy, 随便你起名字 可以吗?
  29. xxx = w1(f1)
  30. xxx()
  31. # 验证答案是可以的,那么既然能随便起名字,那我就起成f1,不就变成了f1(),这样我就在执行f1()的时候执行了w1中的内容
  32. f1 = w1(f1)
  33. f1()
  34. # 上述的所有说明就是装饰器的原理,那么有没有简单的方式呢? 这时候知识点来了
  35. def w1(func):
  36. def inner():
  37. print('-------正在验证权限-----')
  38. func()
  39. return inner
  40. # 这一个@w1就等价于f1 = w1(f1)
  41. @w1
  42. def f1():
  43. print('--------f1---------')
  44. f1()

二、多个装饰器讨论

  1. def w1(func):
  2. def inner():
  3. print('----正在执行w1-----')
  4. func() # 相当于test1()
  5. return inner
  6. def w2(func):
  7. def inner():
  8. print('----正在执行w2-----')
  9. func() # 相当于test()
  10. return inner
  11. @w1 # test = w1(test1)
  12. @w2 # test1 = w2(test) test1指向了w2中的inner 此时inner中有 ----正在执行w2----- 和------test-------
  13. def test():
  14. print('------test-------')
  15. test()
  1. ----正在执行w1-----
  2. ----正在执行w2-----
  3. ------test-------

解释:当程序自上而下进行到@w1时,发现@w1下面并不是一个函数,那么先不处理,继续往下走,走到@w2时,诶,发现了一个函数test,那么开始处理,由上面可知:test1指向了w2中的函数inner,那么此时inner中有----正在执行w2----- 和------test-------,接着w1(test1) 然后返回w1中的inner给test, 那么此时test里面就相当于有本身的----正在执行w1-----和test1指向的----正在执行w2----- 和------test-------。最后调用:test() 

  1. def w1(func):
  2. print('-----正在装饰1----')
  3. def inner():
  4. print('----正在执行w1-----')
  5. func()
  6. return inner
  7. def w2(func):
  8. print('-----正在装饰2-----')
  9. def inner():
  10. print('----正在执行w2-----')
  11. func()
  12. return inner
  13. @w1 # 只要python解释器执行到这部分代码,就会自动装饰,不会等调用才装饰
  14. @w2
  15. def test():
  16. print('------test-------')
  17. # test() 注意我屏蔽了调用
  1. -----正在装饰2-----
  2. -----正在装饰1----

解释:上面已经说到:发现@w1下面并不是一个函数,那么先不处理,所以先处理@w2,装饰@w2完后,再装饰@w1;同时要记住只要python解释器执行到这部分代码,就会自动装饰,不会等调用才装饰。

 

  1. def w1(func):
  2. print('-----正在装饰1----')
  3. def inner():
  4. print('----正在执行w1-----')
  5. func()
  6. return inner
  7. def w2(func):
  8. print('-----正在装饰2-----')
  9. def inner():
  10. print('----正在执行w2-----')
  11. func()
  12. return inner
  13. @w1
  14. @w2
  15. def test():
  16. print('------test-------')
  1. -----正在装饰2-----
  2. -----正在装饰1----
  3. ----正在执行w1-----
  4. ----正在执行w2-----
  5. ------test-------

总结:实在不清楚原理,可以简单理解为:装饰器哪个离函数近,就先装饰哪个, 执行就从上往下执行。

 

三、被装饰的函数有参数

  1. def w1(func):
  2. def inner(a, b): # 如果这里不写两个实参,那么调用test(1,2)会报错
  3. print('-------')
  4. func(a, b) # 如果这里不写两个实参,那么调用def test(a, b):会报错
  5. return inner
  6. @w1
  7. def test(a, b):
  8. print(a+b)
  9. test(1,2)
  10. # 不定长参数的装饰器
  11. def w1(func):
  12. def inner(*args, **kwargs):
  13. print('-------')
  14. func(*args, **kwargs)
  15. return inner
  16. @w1
  17. def test(a, b, c):
  18. print(a+b+c)
  19. test(1,2,3)

四、装饰器装饰有返回值的函数

  1. def w1(func):
  2. def inner():
  3. print('*****')
  4. func()
  5. return inner
  6. @w1
  7. def test():
  8. print('----这是测试----')
  9. return 'handsome'
  10. test() # 打印结果可发现,并没有返回handsome
  11. def w1(func):
  12. def inner():
  13. print('*****')
  14. xxx = func() # 接收返回值handsome
  15. return xxx # 这里写xxx是为了便于理解,有点不规范,所以最好写成ret
  16. return inner
  17. @w1
  18. def test():
  19. print('----这是测试----')
  20. return 'handsome'
  21. ret = test() # 调用函数的同时接收 return xxx 返回的结果
  22. print(ret)

五、装饰器带参数

  1. def w(arg):
  2. def w1(func):
  3. def inner():
  4. print('------')
  5. func()
  6. print('arg的值是%s' % arg)
  7. return inner
  8. return w1
  9. @w('wenwen')
  10. def test():
  11. print('----test------')
  12. test()

解释:1.先执行 w('wenwen')这个函数,这个函数return的结果就是w1这个函数的引用

           2.然后再@w1,使用@w1对test进行装饰

       

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/213287
推荐阅读
  

闽ICP备14008679号