Python – 装饰器(Decorator)
什么情况下可以使用装饰器:函数可以作为参数传递的语言,可以使用装饰?
装饰器的好处:可以极大地简化代码,在不改变原函数的基础上动态修改函数功能,避免每个函数写重复性代码.(可以让已有函数不做任何改动的情况下增加功能.可以使修改函数更加容易,本质上还是一个函数)经常用于以下方面:
1、打印日志 @log
2、检测性能 @performance
3、数据库事务 @transaction
4、URL路由 @post
例:一个只打印“hello”的函数,我们需要再加上“world”;
def addworld(func):
def addFun():
return func()+"world"
return addFun
def printHello():
return"hello"
print(printHello())
world = addworld(printHello)
print(world())print Hello函数内部不做任何修改,但在使用修改后的函数时,需要一个world接受addWorld的返回值,把world指向addFun,再调用world(),这个过程较复杂.所以可以:
def addworld(func):
def addFun():
return func()+" world"
return addFun
@addworld
def printHello():
return "hello"
print(printHello())只需要在需要修改的函数前加一个@addworld,调用方式还是和以前的一样.如果一个函数有两个装饰器:
def addworld(func):
print("===装饰器1===")
def addFun():
return func()+" world"
return addFun
def addHaha(func):
print("===装饰器2===")
def addFun():
return func()+" haha"
return addFun
@addHaha
@addworld
def printHello():
print("===hello==")
return "hello"
print(printHello())当Python的解释器执行到@addHaha时,会将下一行的函数,进行装饰,但下一行为@addWorld,所以解释器需要把@addworld先进行装饰.运行的结果就是,先把addworld运行完成的返回值作为参数传递到addHaha中.带参数的装饰器:
def addNum(func):
def addFun(*args, **kwargs):
ret = func(*args, **kwargs)*2
return ret
return addFun
@addNum
def printSum(a, b):
return a+b
i = printSum(7, 7)
print(i)返回两个数的和的两倍,带参数的装饰器的通用模式:
def fun(funName):
def fun1(*args, **kwargs):
ret =funName(*args, **kwargs)
return ret
return fun1在原有基础上添加一个外部变量,在原有的装饰器外再添加一个函数:
def addNum1(c):
def addNum(func):
def addFun(*args, **kwargs):
ret = func(*args, **kwargs)*2*c
return ret
return addFun
return addNum
@addNum1(5)
def printSum(a, b):
return a+b
print(printSum(7, 7))
addNum1()可用在插入日志、性能测试、事务处理、缓存、权限校验等场景.下面是一个日志功能的装饰器
from functools import wraps deflog(label): defdecorate(func): @wraps(func) def_wrap(*args,**kwargs): try: func(*args,**kwargs) print("name",func.__name__) except Exceptionase: print(e.args) return_wrap returndecorate @log("info") deffoo(a,b,c): print(a+b+c) print("infoo") #decorate=decorate(foo) if__name__==‘__main__‘: foo(1,2,3) #decorate()