@wraps 修饰器:让你的 Python 代码更加简短可爱 | 从简单实例来认识它

开发 前端
本文简单与读者朋友们「科普」一下修饰器,注意到我们这里实际上仅仅修饰了无参数的函数。其实,修饰器还有许多更加优雅用途,比如传入参数 *args, **kwargs ,修饰类 __call__ 等用法。

[[406508]]

我们在上一篇文章(Python实例来认识并发与并行)中用到了 @timer ,在函数定义时,加上一个小小的 @timer ,这样,函数执行结束后,就会自动在控制台汇报自己运行的时间。

比如下面这样:

  1. @timer 
  2. def piper(): 
  3.     for i in range(10000): 
  4.         i = i * i ** 10 
  5.  
  6. piper() 
  7.  
  8. 输出: 
  9. timer: using 0.00600 s 

实际上,这个计时器逻辑 @timer 是我们自己用 Python 中的修饰器特性[1]来实现的。

拆解逻辑

其实我们不用修饰器,自己也能实现计时的逻辑。

  1. def piper(): 
  2.     for i in range(10000): 
  3.         i = i * i ** 10 
  4.  
  5. t = time.time()  # 记录函数开始时时间 
  6. piper() 
  7. print(f"timer: using {time.time() - t :.5f} s")  # 获取函数运行时间并打印 

注意到我们执行函数时,在其上下都包裹上了逻辑。如果我们希望函数自带计时逻辑,那么为了包住原函数,只能去新定义一个函数。

  1. def time_wrapper(func): 
  2.     # func 是一个函数 
  3.     t = time.time() 
  4.     func() 
  5.     print(f"timer: using {time.time() - t :.5f} s"
  6.  
  7. time_wrapper(piper) 
  8.  
  9. 输出: 
  10. timer: using 0.00600 s 

我们想测试某一个函数运行时间时,将函数名输入到 time_wrapper 里面就好。

更优雅的改进

上述代码显然有缺点:

  • 我们在编程时,心智负担增大了;此外,代码更冗长了
  • 如果我们只是希望函数新增一个功能,显然用 time_wrapper 是不行的,因为其并没有改变 piper 本身

于是我们请出今天的主角 修饰器@wraps[2] 。

还用我们的 timer 举例子,我们让所有在 @timer 下的函数,都经过如下处理:

  1. def timer(func): 
  2.     @wraps(func) 
  3.     def inner_func(): 
  4.         t = time.time() 
  5.         rts = func() 
  6.         print(f"timer: using {time.time() - t :.5f} s"
  7.         return rts 
  8.     return inner_func 

以 piper 为例,我们经历了如下变化。

  1. @timer 
  2. def 原始piper(): 
  3.     for i in range(10000): 
  4.         i = i * i ** 10 

实际上,当你再调用 piper 时,你的 piper 内部逻辑早已变为:

  1. def 当前piper(): 
  2.     t = time.time() 
  3.     rts = 原始piper() 
  4.     print(f"timer: using {time.time() - t :.5f} s"
  5.     return rts 

总结

本文简单与读者朋友们「科普」一下修饰器,注意到我们这里实际上仅仅修饰了无参数的函数。其实,修饰器还有许多更加优雅用途,比如传入参数 *args, **kwargs ,修饰类 __call__ 等用法。期待以后我遇到好的应用场景,将经验分享给朋友们。

 

责任编辑:姜华 来源: Piper蛋窝
相关推荐

2024-04-26 11:54:10

Pygments代码Pytho

2019-08-28 09:28:07

SSHOpenSSH运维

2020-05-21 15:14:15

Python列表字典

2020-05-21 08:53:12

Python技术代码

2022-09-19 15:02:24

C语言

2021-01-14 09:59:07

JS代码编码

2015-06-30 16:56:27

敏捷网络石油石化华为

2018-01-31 11:20:48

2022-10-31 07:09:15

拷贝代码项目

2023-10-07 14:49:45

2018-09-06 10:16:39

2014-08-01 09:50:39

Oracle营销云Oracle Eloq

2023-07-03 07:55:25

2021-07-01 10:03:55

Distroless容器安全

2009-11-30 11:33:01

2021-03-03 08:02:13

JavaScript函数字节

2019-04-29 08:31:25

PythonPandas数据

2015-09-17 17:49:13

华三/UIS

2023-11-18 09:07:59

Go语言技巧

2013-08-28 10:20:56

点赞
收藏

51CTO技术栈公众号