函数装饰器

对于某个函数,若是但愿在不改变函数代码的前提下,为该函数增长额外的功能,
那么能够使用装饰器来装饰该函数。闭包

装饰器是一个函数,装饰器接收一个函数做为参数(传入的实参是被装饰的函数),
装饰器的内部嵌套定义另外一个函数,内函数中会引用装饰器的参数,而且装饰器的返回值是内函数。
这样构成了一个闭包。app

为了让内函数接收任意类型的参数,将内函数的形参定义为(*args, **kwargs)。
在函数中首选完成为被装饰函数添加新功能,而后调用被装饰的函数。函数

装饰器的应用语法:
在被装饰函数的前面添加:"@装饰器的函数名"。spa

●为add函数添加log功能。code

#执行流程:
1,被装饰的函数add做为实参传递给装饰器log。
2,返回装饰器的内函数wrapper。
3,将内函数wrapper赋值给名为add(被装饰函数的函数名)的变量。
4,再调用被装饰函数add时,其实调用的是装饰器的内函数wrapper。blog

 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。class

在装饰器的内函数前面添加另一个装饰器:@functools.wraps(装饰器的函数名),
functools.wraps为标准库模块functools中的函数wraps。import

 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))
相关文章
相关标签/搜索