python3装饰器
装饰器作用
简单理解:可以为已有函数添加额外功能
例:
已有2个函数如下
1 def MyFunc1(): 2 print("This is a print function1") 3 4 5 def MyFunc2(): 6 print("This is a print function2")
需求:现想要在函数执行前打印类似(开始使用XXX功能)
不用装饰器方式:
1 def MyFunc1(): 2 print("开始使用MyFunc1功能") 3 print("This is a print function1") 4 5 6 def MyFunc2(): 7 print("开始使用MyFunc2功能") 8 print("This is a print function2")
调用函数时输出:
思考:如果有很多很多的函数,那么每个函数中都要修改(而且这需要在已有函数内部去修改,部分情况下是不允许修改已有函数的),这个方式显然不可靠
采取装饰器的方式做
装饰器模板(写法)
1 def ShowFunction(func): 2 def inner(*args, **kwargs): 3 # 这里写函数执行前的功能 4 ret = func(*args, **kwargs) 5 return ret 6 return inner
利用上述装饰器模板,来写一个上述需求的装饰器
1 # 这是一个装饰器 2 def ShowFunction(func): 3 def inner(*args, **kwargs): 4 name = func.__name__ 5 print("开始使用%s功能" %name) 6 ret = func(*args, **kwargs) 7 return ret 8 return inner 9 10 11 @ShowFunction # @加函数名 这种形式就是使用某个装饰器的写法 12 def MyFunc1(): 13 print("This is a print function1") 14 15 @ShowFunction 16 def MyFunc2(): 17 print("This is a print function2") 18 19 20 MyFunc1() 21 MyFunc2()
效果如下:
现在基本上就能满足上述需求
思考:有时候不是所有的装饰器都是永久装饰函数的,在某些情况下我们会希望装饰器不生效,此时需要用到带有参数的装饰器
此时我们一般会在装饰器外部在套一个函数,来接受一个Flag,在内部用这个Flag来判断是否生效装饰器
1 # 现需要在调用每个函数前说明这是哪个函数,用到带装饰装饰器(可控制是否使装饰器生效) 2 from functools import wraps 3 4 # 这是一个装饰器 5 Flag = 1 6 def FuncWrap(Flag): 7 def ShowFunction(func): 8 @wraps(func) #使外部函数调用函数属性时,不被装饰器影响 9 def inner(*args, **kwargs): 10 if Flag: 11 name = func.__name__ 12 print("开始使用%s功能" %(name)) 13 ret = func(*args, **kwargs) 14 else: 15 ret = func(*args, **kwargs) 16 return ret 17 return inner 18 return ShowFunction 19 20 21 22 @FuncWrap(Flag) # 等于写法-->MyFunc1 = ShowFunction(MyFunc1) 23 def MyFunc1(): 24 print("This is a print function1") 25 26 @FuncWrap(Flag) 27 def MyFunc2(): 28 print("This is a print function2") 29 30 # print(MyFunc1.__name__) 31 MyFunc1() 32 MyFunc2()
我们可以修改Flag的值1(生效)或0(不生效)
扩展:多个装饰器共同装饰一个函数
1 # 这是一个装饰器1 2 def Wrap1(func): 3 def inner(*args, **kwargs): 4 print("start装饰器1") 5 ret = func(*args, **kwargs) 6 print("end装饰器1") 7 return ret 8 return inner 9 10 # 这是一个装饰器2 11 def Wrap2(func): 12 def inner(*args, **kwargs): 13 print("start装饰器2") 14 ret = func(*args, **kwargs) 15 print("end装饰器2") 16 return ret 17 return inner 18 19 @Wrap1 20 @Wrap2 21 def MyFunc1(): 22 print("This is a print function1") 23 24 MyFunc1()
关于多装饰器现象(记住即可):