装饰器及进阶


1、装饰器

装饰器的本质:一个闭包函数

装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展

2、装饰不带参数的函数

 1 import time
 2 def timer(f):            #1
 3     def inner():         #4
 4         start=time.time()  #8
 5         f()                #9
 6         end=time.time()    #12
 7         print(end-start)   #13
 8 
 9     return  inner        #5
10 
11 @timer   #func=time(func)      #3     #6,func的地址变成了inner的内存地址
12 def func():              #2
13     time.sleep(1)        #10
14     print("你好,菜菜")  #11
15 
16 func()                   #7,这里其实是调用inner()

3、装饰带参数的函数

 1 import time
 2 def timer(f):                 #1
 3     def inner(*args,**kwargs):   #4
 4         start=time.time()         #8
 5         f(*args,**kwargs)         #9
 6         end=time.time()           #12
 7         print(end-start)          #13
 8     return inner                    #5
 9 
10 @timer      #f=timer(f)                #3 #6,把inner的内存地址赋值给f
11 def f(a,b):                  #2
12     time.sleep(2)            #10
13     print("***",a,b)         #11
14 f(1,2)                            #7,调用f()实际是调用inner()

4、打印函数名称及带返回值的装饰器

 1 import time
 2 from functools import wraps
 3 def timer(f):
 4     @wraps(f)    #给innner加带参数的装饰器,用来答应被装饰函数的函数名
 5     def inner(*args,**kwargs):
 6         start=time.time()
 7         ret=f(*args,**kwargs)
 8         end=time.time()
 9         print(end-start)
10         return ret
11     return inner
12 
13 @timer      #f=timer(f)
14 def f(a,b):
15     time.sleep(2)
16     print("***",a,b)
17     return '新年好'
18 
19 ret2=f(1,2)
20 print(ret2)   #将f()函数的返回值给打印出来~
21 print(f.__name__)   #如果不加@wraps(f),打印出来是inner的函数名

5、装饰器统一格式

(1)无参数

 1 def wapper(func):
 2     def inner():
 3         '''在被装饰函数之前要做的事'''
 4         func()
 5         '''在被装饰函数之后要做的事'''
 6     return inner
 7 @wapper
 8 def f():
 9     '''要执行的部分'''
10 f()

(2)带参数

 1 def wapper(func):
 2     def inner(*args,**kwargs):
 3 
 4         '''在被装饰函数之前要做的事'''
 5         func(*args,**kwargs)
 6         '''在被装饰函数之后要做的事'''
 7     return inner
 8 
 9 @wapper
10 def f(a,b):
11     pass
12 
13 f(1,2)

6、开放封闭原则

(1)对扩展是开放的

  为什么要对扩展开放呢?

  我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

(2)对修改是封闭的

  为什么要对修改封闭呢?

  就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

  装饰器完美的遵循了这个开放封闭原则。

7、带参数的装饰器(三层装饰器),设置Flage来控制函数的执行

假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?

一个一个的取消掉? 没日没夜忙活3天。。。

过两天你领导想通了,再让你加上。。。

import time
Flage=True
def timmer_out(flag):
    def timer(f):
        def innner():
            if flag:
                start=time.time()
                f()
                end=time.time()
                print(end-start)
            else:
                ret=f()
                return ret
        return innner
  return timer @timmer_out(Flage)
def func(): time.sleep(1) print("你好啊,菜菜") func()

8、多个装饰器修饰一个函数

 1 def wrapper1(func):
 2     def inner1():
 3         print('wrapper1 ,before func')
 4         func()
 5         print('wrapper1 ,after func')
 6 
 7     return inner1
 8 
 9 def wrapper2(func):
10     def inner2():
11         print('wrapper2 ,before func')
12         func()
13         print('wrapper2 ,after func')
14 
15     return inner2
16 
17 @wrapper2
18 @wrapper1
19 def f():
20     print('in f')
21 
22 f()
23 
24 #结果:
25 wrapper2 ,before func
26 wrapper1 ,before func
27 in f
28 wrapper1 ,after func
29 wrapper2 ,after func

优质内容筛选与推荐>>
1、根据ping的返回值判断电脑是否在线
2、ARM裸奔程序设计心得
3、二叉树的简单操作(Binary Tree)
4、ctrl在WINXP中的妙用
5、怎样面对痛苦?


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn