函数装饰器
比方说我们有一个需求,在函数执行前输出一个before,执行后输出一个after,首先我们想到的简单明了的方法就是
1 def example(): 2 print("before") 3 print("我是example函数里的内容") 4 value=(11,22,33) 5 print("after") 6 return value 7 8 res=example() 9 print(res) 10 11 #输出为: 12 #before 13 #我是example函数里的内容 14 #after 15 #(11, 22, 33)
第二种方法(装饰器雏形),代码好像比上的更复杂,输出的内容一样
1 def auto(example): #将函数传入 2 def inner(): 3 print("before") 4 res=example() 5 print("after") 6 return res 7 return inner 8 9 def example(): 10 print("我是example函数里的内容") 11 value=(11,22,33) 12 return value 13 14 example=auto(example) 15 print(example()) 16 17 #输出 18 #before 19 #我是example函数里的内容 20 #after 21 #(11, 22, 33)
如果我们有多个这样的函数呢?在每个函数前都加上before,后面加上after?这样未免有些太麻烦了,所有我们可以采用装饰器来更好的解决问题
1 def auto(example): 2 def inner(): 3 print("before") 4 res=example() 5 print("after") 6 return res 7 return inner 8 9 @auto # 装饰器中的@语法(自动执行) @auto可以看成 xxx=函数名(xxx) 10 def a(): 11 print("我是函数a") 12 13 @auto 14 def b(): 15 print("我是函数b") 16 17 @auto 18 def c(): 19 print("我是函数c") 20 21 a() #输出 before 我是函数a after 22 b() #输出 before 我是函数b after 23 c() #输出 before 我是函数c after
我们先往函数中加入一些注释,然后输出我们执行函数的name和注释文档
def auto(example): def inner(): '''我是函数inner中的注释''' print("before") res=example() print("after") return res return inner @auto # 装饰器中的@语法(自动执行) @auto可以看成 xxx=函数名(xxx) def a(): '''我是函数inner中的注释''' print("我是函数a") @auto def b(): '''我是函数inner中的注释''' print("我是函数b") @auto def c(): '''我是函数inner中的注释''' print("我是函数c") print(a.__name__) # 输出为 inner print(a.__doc__) # 输出为 我是函数inner中的注释
这并不是我们想要的!Ouput输出应该是函数a。这里的函数被inner替代了。它重写了我们函数的名字和注释文档(docstring)。幸运的是Python提供给我们一个简单的函数来解决这个问题,那就是functools.wraps。我们修改上面的代码
#在上面的代码中引入 import functools def auto(example): @functools.wraps(example) #然后加入这条代码 def inner(): '''我是函数inner中的注释''' print("before") res=example() print("after") return res return inner print(a.__name__) # 输出为 a print(a.__doc__) # 输出为 我是函数a中的注释
当装饰器涉及到参数时,代码如下
1 import functools 2 def auto(example): 3 @functools.wraps(example) 4 def inner(*args,**kwargs): #参数传入 5 '''我是函数inner中的注释''' 6 print("before") 7 res=example(*args,**kwargs) #参数传入 8 print("after") 9 return res 10 return inner
装饰器还有类装饰器和更多装饰器用法,详细可以参考地址Python 函数装饰器 | 菜鸟教程 (runoob.com)