装饰器从入门到精通

装饰器从入门到精通:
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
原文地址:https://www.cnblogs.com/d9e84208/p/10598077.html