翼度科技»论坛 编程开发 python 查看内容

Python 装饰器

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
Python 装饰器

python装饰器的本质是: 仅以一个函数为参数,并返回一个函数。 且看以下案例:
  1. def decorator(f):
  2.         print(f.__name__)
  3.         return f
  4. # 1
  5. @decorator
  6. def fun():
  7.         print("run fun")
  8. # 2
  9. fun = decorator(fun)
复制代码
以上两种写法是等价的;装饰器函数会在被装饰的函数 定义完成时执行。
装饰器优点:

  • 不会改变被装饰函数的调用
  • 不用修改被装饰函数的代码
根据使用场景装饰器可以分为几种:
一次性装饰器

一次性装饰器;不对被装饰函数进行任何操作,原样返回被装饰的函数;仅在被装饰函数定义时进行操作。
  1. funcs = []
  2. def decorator(f):
  3.         funcs.append(f)        # 将函数保存到全局list中去
  4.         return f
  5. @decorator
  6. def fun():
  7.         print("run fun")
复制代码
包装装饰器

包装装饰器;一般是在被装饰函数执行前后做一些额外的操作,或者对被装饰函数计算的结果进行操作。
  1. import time
  2. def decorator(f):
  3.         def wrapper(*args, **kwds): # 不确定被装饰函数的参数,使用万能形参
  4.                 t1 = time.time()
  5.                 result = f(*args, **kwds) # 执行被装饰函数
  6.                 t2 = time.time()
  7.                 print(f.__name__, "执行耗时", t2-t1)
  8.                 return result
  9.         return wrapper
  10. @decorator
  11. def fun():
  12.         time.sleep(2)
  13.         print("run fun")
  14. # fun = decorator(fun)
  15. # 此时 fun 已经变成了 wrapper 函数;已经被decorator返回的wrapper覆盖
复制代码
配置装饰器

即有带参数的装饰器,此装饰器可能是为了给被装饰函数提供额外的信息;或者需要用户自己添加配置。
我们只看wrapper函数是不是和上文的一次性装饰器一样呢
  1. def decorator(name):
  2.         def wrapper(f):
  3.                 f.name = name
  4.                 return f
  5.         return wrapper
  6. @decorator("fun1")
  7. def fun():
  8.         print("run fun")
  9. # fun = decorator("fun1")(fun)
  10. print(fun.name)
  11. fun()
复制代码
配置包装装饰器

配置包装装饰器,即有装饰器配置项和修改被包装函数执行流程的装饰器;
  1. import time
  2. def decorator(name): # 配置选项
  3.         def setname(f): # 包装被装饰的函数
  4.                 f.name = name  # 闭包获取 配置选项
  5.                 def wrapper(*args, **kwds): # 返回的最终函数
  6.                         t1 = time.time()
  7.                         result = f(*args, **kwds) # 执行被包装的函数
  8.                         t2 = time.time()
  9.                         print(f.name, "执行耗时", t2-t1)
  10.                         return result
  11.                 return wrapper
  12.         return setname
  13. @decorator("fun1")
  14. def fun():
  15.         print("run fun")
复制代码
类装饰器

@decorator本质是一次函数调用;对应到类上就是__init__()调用;即类的实例化。如果类实现了__call__()方法,类的实例对象就可以像函数一样调用。
  1. class Decorator:
  2.         def __init__(self, name):
  3.                 self.name = name
  4.        
  5.         def __call__(self, f):
  6.                 self.f = f
  7.                 return self.wrapper
  8.        
  9.         def wrapper(self, *args, **kwds):
  10.                 print(self.name)
  11.                 return self.f(*args, **kwds)
  12. @Decorator("name")
  13. def fun():
  14.         print("run fun")
复制代码
装饰类的装饰器
  1. def decorator(cls):
  2.         def wrapper(*args, **kwds):
  3.                 obj = cls(*args, **kwds)
  4.                 return obj
  5.         return wrapper
  6. @decorator
  7. class Test:
  8.         def __init__(self):
  9.                 pass
  10. print(Test)
  11. print(Test())
  12. # <function decorator.<locals>.wrapper at 0x7fd9ecba5280>
  13. # <__main__.Test object at 0x7fd9ecc22550>
复制代码
多层装饰器
  1. def a(f):
  2.         print("a 装饰器执行")
  3.         def _a():
  4.                 print("函数执行 调用_a 装饰器")
  5.                 return f()
  6.         return _a
  7. def b(f):
  8.         print("b 装饰器执行")
  9.         def _b():
  10.                 print("函数执行 调用_b 装饰器")
  11.                 return f()
  12.         return _b
  13.        
  14. def c(f):
  15.         print("c 装饰器执行")
  16.         def _c():
  17.                 print("函数执行 调用_c 装饰器")
  18.                 return f()
  19.         return _c
  20. @a
  21. @b
  22. @c
  23. def fun():
  24.         print("fun run")
  25. # fun = a( b( c(fun )) )
  26. fun()
  27. # -----程序输出—-----
  28. # c 装饰器执行
  29. # b 装饰器执行
  30. # a 装饰器执行
  31. # 函数执行 调用_a 装饰器
  32. # 函数执行 调用_b 装饰器
  33. # 函数执行 调用_c 装饰器
  34. fun run
复制代码
有什么建议意见请留言讨论
谢谢观看
浪费了你人生中的几秒真的很抱歉(≧ ﹏ ≦)

来源:https://www.cnblogs.com/main-warma/p/17938028
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具