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()