• 装饰器


    1、默写下面的函数

     1 import time
     2 def func():
     3     time.sleep(0.2)
     4     print("今天放假")
     5 def timme(f):  # 这里的函数名不能直接用time(),不然会报错,很可能是跟系统函数冲突
     6     def inner():
     7         Start_time = time.time()
     8         f()
     9         End_time = time.time()
    10         print(End_time - Start_time)
    11 
    12     return inner
    13 func = timme(func)
    14 func()
    不想修改函数的调用方式,但是还想在原来的函数前后添加功能
    timmer就是一个装饰器函数,只是对一个函数有一些装饰作用
    timmer就是装饰器函数,timmer()里面的f()就是被装饰函数

    2、装饰器的基本原则

     原则:开放封闭原则

    开放:对扩展是开放的

    封闭:对修改是封闭的

    3、语法糖

     把上面的装饰器用语法糖方式重新定义

     1 def timme(f):
     2     def inner():
     3         Start_time = time.time()
     4         f()
     5         End_time = time.time()
     6         print(End_time - Start_time)
     7 
     8     return inner
     9 
    10 @timme                #语法糖,@装饰器函数名,这句话等价下面的func = timme(func)
    11 def func():          #紧挨着的是被装饰函数
    12     time.sleep(0.2)
    13     print("今天放假")
    14 #func = timme(func)   #用了语法糖以后,这条代码就被省去了,
    15 func()

    4、下面被装饰函数func加上返回值以后,当我们调用func()时候有返回值吗

     1 def timme(f):
     2     def inner():
     3         Start_time = time.time()
     4         f()
     5         End_time = time.time()
     6         print(End_time - Start_time)
     7 
     8     return inner
     9 
    10 @timme                #语法糖,@装饰器函数名
    11 def func():          #紧挨着的是被装饰函数
    12     time.sleep(0.2)
    13     print("今天放假")
    14     return '过节学习'
    15 ret = func()
    16 print(ret)
    1 0.2000114917755127
    2 None
    参考结果
     1 def timme(f):
     2     def inner():
     3         Start_time = time.time()
     4         ret = f()
     5         End_time = time.time()
     6         print(End_time - Start_time)
     7         return ret
     8     return inner
     9 
    10 @timme                #语法糖,@装饰器函数名
    11 def func():          #紧挨着的是被装饰函数
    12     time.sleep(0.2)
    13     print("今天放假")
    14     return '过节学习'
    15 ret = func()
    16 print(ret)
    有返回值的参考代码

    5、装饰带参数函数的装饰器

     带一个参数的装饰器

     1 def timme(f):
     2     def inner(a):
     3         Start_time = time.time()
     4         ret = f(a)
     5         End_time = time.time()
     6         print(End_time - Start_time)
     7         return ret
     8     return inner
     9 
    10 @timme                #语法糖,@装饰器函数名
    11 def func(a):          #紧挨着的是被装饰函数
    12     time.sleep(0.2)
    13     print("今天放假",a)
    14     return '过节学习'
    15 ret = func(2)
    16 print(ret)
    1 今天放假 2
    2 0.2000114917755127
    3 过节学习
    参考结果

    带两个参数的装饰器

     1 def timme(f):
     2     def inner(*args):
     3         Start_time = time.time()
     4         ret = f(*args)  # 这里还需要用*把多个参数打散传入
     5         End_time = time.time()
     6         print(End_time - Start_time)
     7         return ret
     8 
     9     return inner
    10 
    11 @timme  # 语法糖,@装饰器函数名
    12 def func2(a):  # 紧挨着的是被装饰函数
    13     time.sleep(0.2)
    14     print("今天放假", a)
    15     return '过节学习'
    16 
    17 
    18 @timme  # 语法糖,@装饰器函数名
    19 def func3(a, b):  # 紧挨着的是被装饰函数
    20     time.sleep(0.2)
    21     print("今天放假", a, b)
    22     return '过节学习'
    23 
    24 
    25 ret2 = func2(2)
    26 print(ret2)
    27 ret3 = func3(3, 4)
    28 print(ret3)
    1 今天放假 2
    2 0.2000114917755127
    3 过节学习
    4 今天放假 3 4
    5 0.2000114917755127
    6 过节学习
    参考结果

    6、包含关键字的装饰器

     1 def timme(f):
     2     def inner(*args,**kwargs):
     3         Start_time = time.time()
     4         ret = f(*args,**kwargs)  # 这里还需要用*把多个参数打散传入
     5         End_time = time.time()
     6         print(End_time - Start_time)
     7         return ret
     8 
     9     return inner
    10 
    11 
    12 @timme  # 语法糖,@装饰器函数名
    13 def func2(a,b):  # 紧挨着的是被装饰函数
    14     time.sleep(0.2)
    15     print("今天放假", a,b)
    16     return '过节学习'
    17 
    18 
    19 ret = func2(4,6)
    20 print(ret)
    21 ret2 = func2(2,b = 9)
    22 print(ret2)
    1 今天放假 4 6
    2 0.2000114917755127
    3 过节学习
    4 今天放假 2 9
    5 0.2000112533569336
    6 过节学习
    参考结果

    7、装饰器的固定格式

     1 def wrapper(f):                          #装饰函数,f是被装饰函数
     2     def inner(*args,**kwargs):
     3         '''在被装饰函数之前要做的事情'''
     4         ret = f(*args,**kwargs)          #被装饰函数
     5         '''在被装饰函数之后要做的事情'''
     6         return ret
     7     return inner
     8 
     9 @wrapper                                 #语法糖,@装饰器函数名,等价于func = wrapper(func)
    10 def func(a,b):                          #被装饰函数
    11     time.sleep(0.5)
    12     print("放假最后一天了",a,b )
    13     return '假期是充实的'
    14 
    15 ret = func(b = 9,a = 3)                 #实际执行的是inner函数
    16 print(ret)
    1 放假最后一天了 3 9
    2 假期是充实的
    参考结果

     

     8、装饰器的聚合与打散

    传参:聚合,就是说传参的时候是把几个参数一起传给函数
    调用:打散,就是说具体调用的时候是一个一个参数来使用,那么好比打散来用
     1 def wrapper(func):
     2     def inner(*args,**kwargs):
     3         print("在被装饰之前做的事情")
     4         ret = func(*args,**kwargs)
     5         print("被装饰之后做的事情")
     6         return ret
     7     return inner
     8 
     9 @wrapper
    10 def func(day):
    11     print("节后第%s天"%day)
    12 
    13     return "继续加油干"
    14 
    15 ret = func(1)
    16 print(ret)

    上面代码结果是:

    1 在被装饰之前做的事情
    2 节后第1天
    3 被装饰之后做的事情
    4 继续加油干
    参考结果

     9、带参数的装饰器

    一个装饰器一般就三层,最外一层是带参数,方便用参数的设置来决定是否进行装饰,这样避免挨个挨个进行去掉装饰

     1 import time
     2 Flag = False
     3 def timmer_out(Flag):
     4     def timmer(func):
     5         def inner(*args,**kwargs):
     6             if Flag:
     7                 start_time = time.time()
     8                 ret = func(*args,**kwargs)
     9                 end_time = time.time()
    10                 print(end_time - start_time)
    11                 return ret
    12             else:
    13                 ret = func(*args, **kwargs)
    14                 return  ret
    15         return inner
    16     return timmer
    17 #timmer = timmer_out(Flag),timmer_out后面带括号就是函数调用
    18 @timmer_out(Flag)
    19 def get():
    20     time.sleep(0.2)
    21     print("快上班了")
    22 
    23 get()
    1 快上班了
    参考结果

    10、装饰器进阶:多个装饰器同时装饰同一个函数

     1 def wrapper1(func):
     2     def inner1(*args,**kwargs):
     3         print("wrapper1开始装饰")
     4         ret = func(*args,**kwargs)
     5         print("wrapper1装饰结束")
     6         return ret
     7     return inner1
     8 
     9 def wrapper2(func):
    10     def inner2(*args,**kwargs):
    11         print("wrapper2开始装饰")
    12         ret = func(*args,**kwargs)
    13         print("wrapper2装饰结束")
    14         return ret
    15     return inner2
    16 
    17 def wrapper3(func):
    18     def inner3(*args,**kwargs):
    19         print("wrapper3开始装饰")
    20         ret = func(*args,**kwargs)
    21         print("wrapper3装饰结束")
    22         return ret
    23     return inner3
    24 
    25 @wrapper3
    26 @wrapper2
    27 @wrapper1
    28 def f(a):
    29     print("输入的数是:",a)
    30     return "返回结束"
    31 
    32 print(f(666))
    1 wrapper3开始装饰
    2 wrapper2开始装饰
    3 wrapper1开始装饰
    4 输入的数是: 666
    5 wrapper1装饰结束
    6 wrapper2装饰结束
    7 wrapper3装饰结束
    8 返回结束
    参考结果

    多个装饰器同时装饰同一个函数的执行顺序:






  • 相关阅读:
    左边定宽, 右边自适应方案
    C3 Transitions, Transforms 以及 Animation总结
    ES6中的Rest参数和默认参数
    Vue项目搭建流程 以及 目录结构构建
    在vue组件的stylus样式总 取消search类型的input按钮中默认样式
    JS与JQ绑定事件的几种方式.
    `<img>`放到`<div>`中底部出现空隙 以及解放方案.
    总结
    一道简单的编程题_ 关于定时器.
    mybatis-resultType和resultMap
  • 原文地址:https://www.cnblogs.com/xiaofei1106/p/10665820.html
Copyright © 2020-2023  润新知