函数装饰器
对于某个函数,如果希望在不改变函数代码的前提下,为该函数增加额外的功能,
那么可以使用装饰器来装饰该函数。
装饰器是一个函数,装饰器接收一个函数作为参数(传入的实参是被装饰的函数),
装饰器的内部嵌套定义另一个函数,内函数中会引用装饰器的参数,并且装饰器的返回值是内函数。
这样构成了一个闭包。
为了让内函数接收任意类型的参数,将内函数的形参定义为(*args, **kwargs)。
在函数中首选完成为被装饰函数添加新功能,然后调用被装饰的函数。
装饰器的应用语法:
在被装饰函数的前面添加:"@装饰器的函数名"。
●为add函数添加log功能。
#执行流程:
1,被装饰的函数add作为实参传递给装饰器log。
2,返回装饰器的内函数wrapper。
3,将内函数wrapper赋值给名为add(被装饰函数的函数名)的变量。
4,再调用被装饰函数add时,其实调用的是装饰器的内函数wrapper。
1 #add函数的装饰器函数。 2 def log(func): 3 def wrapper(*args, **kwargs): 4 print("函数%s被调用了" % func.__name__) 5 return func(*args, **kwargs) 6 return wrapper 7 8 #添加标记@log,对函数add应用装饰器。相当于调用了add = log(add) 9 @log 10 def add(sum1, sum2): 11 print(sum1, sum2) 12 return sum1 + sum2 13 14 #调用方法和通常一样。打印调用结果。 15 print(add(1, 2)) 16 17 #打印实际被调用的函数名。 18 print(add.__name__) #结果为wrapper。
●实现被装饰后,函数名依旧是add。
在装饰器的内函数前面添加另外一个装饰器:@functools.wraps(装饰器的函数名),
functools.wraps为标准库模块functools中的函数wraps。
1 import functools 2 3 def log2(func): 4 @functools.wraps(func) 5 def wrapper(*args, **kwargs): 6 print("函数%s被调用了" % func.__name__) 7 return func(*args, **kwargs) 8 return wrapper 9 10 @log2 11 def add2(sum1, sum2): 12 print(sum1, sum2) 13 return sum1 + sum2 14 15 print(add2(1, 2)) 16 17 print(add2.__name__) #结果为add2。
●给装饰器传递额外参数。
需要3层嵌套装饰器。
对于@log3('6月','18日'),相当于执行语句:add3 = log3('6月','18日')(add3)。
1 def log3(month, day): 2 def decorator(func): 3 @functools.wraps(func) 4 def wrapper(*args, **kwargs): 5 print("%s%s, 函数%s被调用了" % (month, day, func.__name__)) 6 return func(*args, **kwargs) 7 return wrapper 8 return decorator 9 10 @log3('6月', '18日') 11 def add3(sum1, sum2): 12 print(sum1, sum2) 13 return sum1 + sum2 14 15 print(add3(1, 2))
------山的那一边