Python函数装饰器(functional decorators)就是拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能。
这个函数的特殊之处在于它的返回值也是一个函数,这个函数是内嵌“原”函数的函数。
例如写一个打印hello的函数,如下
def hello():
print('hello')
if __name__=='__main__':
hello()
输出结果如下:
如果我们要修改函数内容,对函数进行监控,可以直接修改代码。但往往由于工作量很大,不可能一个一个改。所以要将其独立出来进行拓展。在Java里面称为注解,在Python中称为装饰器。
装饰器就是给原来的函数加了一个包装(wrapper),利用包装对原函数进行修改与装饰,从而达到拓展功能的目的。
在这里我们增加一个简单的装饰器:
def log(func): #装饰器核心
def wrapper(): #定义具体装饰过程
print('before calling', func.__name__)
func()
print('end calling', func.__name__)
return wrapper
@log
def hello(): #增加装饰器,func相当于一个函数指针
print('hello')
if __name__=='__main__': #主函数
hello() #相当于调用log(hello())
其输出结果如下:
如果带参数怎么办呢?带参数可以如下处理
def log(func): #装饰器核心
def wrapper(name): #定义具体装饰过程
print('before calling', func.__name__)
func(name)
print('end calling', func.__name__)
return wrapper
@log
def hello(name):
print('hello',name)
if __name__=='__main__': #主函数
hello('CSDN')
输出结果如下
因为参数有很多,所以我们也可以用Python中的通用参数表示。
一个*表示无名字参数,两个**表示有名字参数,即:
*args:无名字参数
**kvargs:有名字参数(有名字无名字就是有没有参数名)
代码就可以改写为如下,增加年龄:
def log(func): #装饰器核心
def wrapper(*args,**kvargs): #定义具体装饰过程
'''
#args为无名字参数
##kvargs为有名字参数
'''
print('before calling', func.__name__)
print('args:',args,'kvargs:',kvargs)
func(*args,**kvargs)
print('end calling', func.__name__)
return wrapper
@log
def hello(name,age):
print('hello',name,age)
if __name__=='__main__': #主函数
#hello('CSDN',2)
hello(name='CSDN',age=2)
运行结果如下:
我们发现kvargs为空。说明CSDN和2都是无名字的变量,如果将
hello('CSDN',2)
改为
hello(name='CSDN',age=2)
再次打印结果如下:
这个时候CSDN和2就变成了有名字的变量。
再进阶一下,在写装饰器的时候log(可以定义其他的)是分等级的,也就是说其可以带参数,这个时候代码思想都是一致的,就是再在装饰器内加一层即可。
def log(level,*args,**kvargs): #装饰器核心
def inner(func): #嵌套两层
def wrapper(*args,**kvargs): #定义具体装饰过程
print(level,'before calling', func.__name__)
print(level,'args:',args,'kvargs:',kvargs)
func(*args,**kvargs)
print(level,'end calling', func.__name__)
return wrapper
return inner
@log(level='INFO')
def hello(name,age):
print('hello',name,age)
if __name__=='__main__': #主函数
#hello('CSDN',2)
hello(name='CSDN',age=2)
结果如下:
唠唠叨叨说了一点,最后提炼一下,装饰器大体思路如下:
def myDecorator(...): #定义装饰器,可能带参数
def decorator(func): #装饰器核心,以被装饰的函数对象为参数,返回装饰后的函数对象
def wrapper(*args, **kvargs): #装饰的过程,参数列表适应不同参数的函数
... #修改函数调用前的行为
func(*args, **kvargs) #调用函数
... #修改函数调用后的行为
return wrapper
return decorator
@myDecorator(...):
def myFunc(...): #给函数加上装饰器,自己定义的功能函数
if __name__=='__main__': #主函数
欢迎交流!