• 装饰器从入门到精通


    装饰器从入门到精通:
    1.背景:年底到了,又要发年终奖了,可是怎么发比较好呢?
      你碰到了一个不懂技术的老大,老大说了,把大家把写得最为
      得意的一段代码拿出来跑时间,咱们凭实力说话!!!于是乎老板
      把测试时间的任务交给你了,那么问题来了,到底怎么解决好呢?

    2.于是乎,经过仔细思考你想到了一个方案,以前学数据结构的时候不是
      测试代码效率的办法:引用系统自带的时间模块即可:

      import time

      start = time.time()
      func()
      end = time.time()
      print(end - start)

    3.开放封闭原则:
      开放:对扩展是开放的
      封闭:对修改是封闭的
    4.好了不废话了,很显然,上面的代码是不满足这个原则的,接下来
      今天的主角登场了,装饰器!!!
    5.初识装饰器:

     1 import time
     2 
     3 
     4 def timmer(f):
     5     def inner():
     6         start = time.time()
     7         f()
     8         end = time.time()
     9         print(end - start)
    10 
    11     return inner
    12 
    13 
    14 def func():
    15     time.sleep(0.1)
    16     # 时间太短无法测试 所以sleep一下
    17     print("hello world")
    18 
    19 
    20 func = timmer(func)
    21 # 这里面讲func作为参数传到里面去执行了一趟!!!
    22 # 返回的func实际上是inner
    23 func()
    24 """
    25 hello world
    26 0.10023927688598633
    27 """
    View Code

    实际上这就是一个闭包嘛,地球人真麻烦取这么多名字干嘛!!!

    6.语法糖
      老是这么写:func = timmer(func),实在是繁琐,于是呢人们又发明了一个
      新的写法来代替上面这句话:在被装饰的函数前面加上@起装饰作用的函数
      上面这个就写成这样了:

     1 import time
     2 
     3 
     4 def timmer(f):
     5     def inner():
     6         start = time.time()
     7         f()
     8         end = time.time()
     9         print(end - start)
    10 
    11     return inner
    12 
    13 
    14 @timmer  # 相当于 func = timmer(func)
    15 def func():
    16     time.sleep(0.1)
    17     # 时间太短无法测试 所以sleep一下
    18     print("hello world")
    19 
    20 
    21 func()
    22 """
    23 hello world
    24 0.10023927688598633
    25 """
    View Code

    7.参数问题

      如果被装饰的函数里面有参数怎么办?装饰之后的func实际上是inner,而func又在

    inner里面执行,所以我把参数给inner,顺便再返回一下就可以了。

     1 import time
     2 
     3 
     4 def timmer(f):
     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 
    12     return inner
    13 
    14 
    15 @timmer  # 相当于 func = timmer(func)
    16 def func(a, b):
    17     time.sleep(0.1)
    18     # 时间太短无法测试 所以sleep一下
    19     print("hello world")
    20     return a + b
    21 
    22 
    23 a = func(1, 2)
    24 print(a)
    25 """
    26 hello world
    27 0.10096383094787598
    28 3
    29 """
    View Code

    8.装饰器公式 ===>万能金刚

     1 import time
     2 
     3 
     4 def outer(f):
     5     def inner(*args, **kwargs):
     6         start = time.time()
     7         ret = f(*args, **kwargs)
     8         end = time.time()
     9         print(start - end)
    10         return ret
    11 
    12     return inner
    13 
    14 
    15 @outer
    16 def func():
    17     pass
    View Code

    9.高阶装饰器(带参数的装饰器)

     1 def route(rule, **options):  # 从右往左执行 第一层实际上是传递参数
     2     def decorator(f):
     3         def inner(*args, **kwargs):
     4             print(options)
     5             # dic =
     6             print({**options})
     7             # print(**options)
     8             endpoint = options.pop("endpoint", f.__name__)  # 弹出字典里面的值
     9             print("被装饰的函数为:", endpoint)
    10             print(rule)
    11             res = f(*args, **kwargs)
    12             print("in decorator")
    13             print(id(f))
    14             return res
    15 
    16         return inner
    17 
    18     return decorator
    19 
    20 
    21 dic = {"name": "dgf", "age": 18}
    22 
    23 
    24 @route('/我是路由/', name="dgf")  # 这句话等同于 func=outer(func)
    25 def printIn(str):
    26     # print(id(printIn))
    27     print('h')
    28     return str
    29 
    30 
    31 ret = printIn("hello world")
    32 print(ret)
     1 import time
     2 
     3 
     4 def timmer_out(flag):
     5     def timmer(f):
     6         def inner(*args, **kwargs):
     7             if flag:
     8                 start = time.time()
     9                 ret = f(*args, **kwargs)
    10                 end = time.time()
    11                 print(end - start)
    12                 return ret
    13             else:
    14                 ret = f(*args, **kwargs)
    15                 return ret
    16 
    17         return inner
    18 
    19     return timmer
    20 
    21 
    22 @timmer_out(True)
    23 def func():
    24     time.sleep(0.1)
    25     print("我是func")
    26 
    27 
    28 func()
    29 """
    30 我是func
    31 0.10094308853149414
    32 """
    View Code

    再将参数改为FALSE

     1 import time
     2 
     3 
     4 def timmer_out(flag):
     5     def timmer(f):
     6         def inner(*args, **kwargs):
     7             if flag:
     8                 start = time.time()
     9                 ret = f(*args, **kwargs)
    10                 end = time.time()
    11                 print(end - start)
    12                 return ret
    13             else:
    14                 ret = f(*args, **kwargs)
    15                 return ret
    16 
    17         return inner
    18 
    19     return timmer
    20 
    21 
    22 @timmer_out(False)
    23 def func():
    24     time.sleep(0.1)
    25     print("我是func")
    26 
    27 
    28 func()
    29 """
    30 我是func
    31 """
    View Code

    这里实际上要分两步看这个问题

    10.多个装饰器装饰一个函数

     1 def func1(f):
     2     def inner(*args, **kwargs):
     3         print("fun1 start")
     4         func_ret = f()
     5         print("fun1 end")
     6         return func_ret
     7 
     8     return inner
     9 
    10 
    11 def func2(f):
    12     def inner(*args, **kwargs):
    13         print("fun2 start")
    14         func_ret = f()
    15         print("fun2 end")
    16         return func_ret
    17 
    18     return inner
    19 
    20 
    21 def func3(f):
    22     def inner(*args, **kwargs):
    23         print("fun3 start")
    24         func_ret = f()
    25         print("fun3 end")
    26         return func_ret
    27 
    28     return inner
    29 
    30 
    31 @func3
    32 @func2
    33 @func1
    34 def func():
    35     print("func")
    36 
    37 
    38 if __name__ == "__main__":
    39     func()
    40 
    41 """
    42 fun3 start
    43 fun2 start
    44 fun1 start
    45 func
    46 fun1 end
    47 fun2 end
    48 fun3 end
    49 
    50 """
    View Code
  • 相关阅读:
    CodeForce20C
    2019年9月末周java面试题总结
    java复习--框架部分
    java复习--Oracle数据库
    java复习--Web部分
    java复习--基础部分
    springboot中使用poi导入excel文件
    springboot中使用poi导出excel文件
    20.java自定义注解
    Redis入门
  • 原文地址:https://www.cnblogs.com/d9e84208/p/10598077.html
Copyright © 2020-2023  润新知