python —— 装饰器函数

装饰器                                                                 

装饰器原则:遵循开放封闭原则。对外扩展开放;对修改是封闭。

装饰器的作用:在不改变原函数的情况下,在函数前后添加新的功能

装饰器的本质:闭包函数

先看思维导图能更好的学习装饰器函数                                     

1、基础版本的装饰器模板:                                                         

 1 def wrapper(func):
 2     def inner(*args,**kwargs):
 3         print('被装饰函数前添加内容')
 4         ret = func(*args,**kwargs)   #被装饰函数,在这里指 my_func 函数
 5         print('被装饰函数后添加内容')
 6         return ret
 7     return inner
 8 
 9 @wrapper   # 等价于 my_func = wrapper(my_func)相当于:my_func = inner
10 def my_func():   #正常定义的函数,也就是要被装饰的函数
11     c = 1+3
12     return c
13 
14 #函数调用
15 g = my_func()   # my_func ==inner
16 print(g) # 4
基础版装饰

直接过程如图所示:

2、练习:在不改变定义的my_func程序中,测试代码执行的时间? 

 1 import  time
 2 def wrapper(func):
 3     def inner(*args,**kwargs):
 4         start_time = time.time()
 5         ret = func(*args,**kwargs) #被装饰函数,在这里指 my_func 函数
 6         time.sleep(0.01)
 7         end_time = time.time()
 8         print('程序执行时间为:',(end_time - start_time))
 9         return ret
10     return inner
11 
12 @wrapper   # 等价于 my_func = wrapper(my_func)相当于:my_func = inner
13 def my_func():   #正常定义的函数,也就是要被装饰的函数
14     c = 1+3
15     return c
16 
17 #函数调用
18 g = my_func()   # my_func ==inner
19 print(g) # 4
测试代码执行时间

如果有一天同事想取到您这个函数明德时候,上述装饰器就不能正确的给出,存在缺陷,如图:

解决办法:

 1 import  time
 2 from functools import wraps    
 3 def wrapper(func):
 4     @wraps(func)
 5     def inner(*args,**kwargs):
 6         start_time = time.time()
 7         ret = func(*args,**kwargs) #被装饰函数,在这里指 my_func 函数
 8         time.sleep(0.01)
 9         end_time = time.time()
10         print('程序执行时间为:',(end_time - start_time))
11         return ret
12     return inner
13 
14 @wrapper   # 等价于 my_func = wrapper(my_func)相当于:my_func = inner
15 def my_func():   #正常定义的函数,也就是要被装饰的函数
16     c = 1+3
17     return c
18 
19 #函数调用
20 g = my_func()   # my_func ==inner
21 print(g) # 4
22 print(my_func.__name__)    # my_func   获取函数名
完美装饰器

3、函数是可以传参的,那么装饰器能否传参呢?                           

假如:领导要检测您程序运行时间,我们定义装饰器函数,检测过后,要如何删除装饰或者关闭装饰器呢?

 1 import  time
 2 inp = input('是否开启装饰器(y/n):')
 3 flag = True if inp == 'y' else False   #装饰器开关标志位
 4 def outer(flag):
 5     def wrapper(func):
 6         def inner(*args,**kwargs):
 7             if flag:
 8                 start_time = time.time()
 9                 ret = func(*args,**kwargs) #被装饰函数,在这里指 my_func 函数
10                 time.sleep(0.01)
11                 end_time = time.time()
12                 print('程序执行时间为:',(end_time - start_time))
13             else:
14                 ret = func(*args,**kwargs)
15             return ret
16         return inner
17     return wrapper
18 
19 @outer(flag)   #先执行outer(flag),返回wrapper函数:--》 @wrapper
20 def my_func():   #正常定义的函数,也就是要被装饰的函数
21     c = 1+3
22     return c
23 
24 #函数调用
25 g = my_func()  # my_func ==inner
26 print(g)  #4
装饰器参数(可以控制装饰的开启与关闭)

 4、 有些时候,我们也会用到多个装饰器装饰同一个函数的情况。 

wrapper1(func):
    def inner1(*args,**kwargs):
        ret = func(*args,**kwargs)  #被装饰的函数
        return ret
    return inner1

def wrapper2(func):
    def inner2(*args,**kwargs):
        ret = func(*args,**kwargs)  #被装饰的函数
        return ret
    return inner2

@wrapper1
@wrapper2
def my_func():
    print('*********')
    return('11111')
多个装饰器装饰一个函数

 

posted @ 2019-06-04 11:06  自在呼吸  阅读(86)  评论(0)    收藏  举报