装饰器

  通过使用闭包函数(嵌套函数),来达到不改变原方法,而对原方法添加功能的作用

  

 1 import time
 2 from functools import wraps
 3 
 4 
 5 def timer(f):
 6     @wraps(f)
 7     def inner(*args,**kwargs):
 8         start = time.time()
 9         res = f(*args,**kwargs)
10         end = time.time()
11         print(end - start)
12         return res
13     return inner
14 
15 
16 @timer  #func = timer(func(a))
17 def func(a):
18     '''this is a function'''
19     return f'function:{a}'
20 
21 res = func('f')
22 print(res)
23 print(func.__name__)
24 print(func.__doc__)

  对func函数添加计算时间的功能,16行@语法,称之为语法糖,等同于 func = timer(func(a));

  __name__ 和__doc__方法,可查看函数的方法和注释,由于使用了装饰器,故显示的都为装饰器中的属性,若要显示原来属性,则使用functools的wrap方法对装饰的函数进行装饰;

  控制装饰器的执行

  对装饰器函数在外包一层函数,使用布尔值进行判断调用

 

 1 Flag = True
 2 def outer(Flag):
 3     def timer(f):
 4         @wraps(f)
 5         def inner(*args,**kwargs):
 6             if Flag:
 7                 start = time.time()
 8                 res = f(*args,**kwargs)
 9                 end = time.time()
10                 print(end - start)
11             else:
12                 res = f(*args,**kwargs)
13             return res
14         return inner
15     return timer
16 
17 @outer(Flag)
18 def func(a):
19     '''this is a function'''
20     return f'function:{a}'
21 
22 res = func('hello')
23 print(res)

通过修改布尔值,就可调控该装饰器是否执行

  多个装饰器

  当有多个装饰器时,离函数最近的装饰器先执行

 1 def wrapper1(func):
 2     def inner():
 3         print('wrapper1 ,before func')
 4         func()
 5         print('wrapper1 ,after func')
 6     return inner
 7 
 8 def wrapper2(func):
 9     def inner():
10         print('wrapper2 ,before func')
11         func()
12         print('wrapper2 ,after func')
13     return inner
14 
15 @wrapper2
16 @wrapper1
17 def f():
18     print('in f')
19 
20 f()

  实际执行顺序为wrapper1,然后是wrapper2;在调用wrapper1时,返回的为wrapper1的inner函数,此时对该inner函数,进行wrapper2的装饰,故输出如下图。

        

  该输出如,照镜子,f为镜子,我称之为镜子输出

 

posted @ 2018-11-30 23:32  springy  阅读(166)  评论(0编辑  收藏  举报