鱼C论坛

 找回密码
 立即注册
查看: 2300|回复: 2

[技术交流] Python 小技巧 054:自定义装饰器

[复制链接]
发表于 2020-1-21 12:25:20 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 zltzlt 于 2020-1-23 20:27 编辑

Python 自定义装饰器


简而言之,Python 的装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数。

使用 Python 装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。

Python 的内置装饰器有 property、classmethod 和 staticmathod。除了使用内置的装饰器我们还可以定义自己的装饰器。

先来看一个最简单的例子:

  1. >>> def deco(func):
  2.         def wrapper(*args, **kwargs):
  3.                 print("进入装饰器...")
  4.                 func(*args, **kwargs)
  5.                 print("离开装饰器...")
  6.         return wrapper
复制代码


这里的 deco 函数就是装饰器,可以看到,deco 装饰器返回了一个 wrapper 函数。我们不妨来测试一下这个装饰器:

  1. >>> @deco
  2. def test():
  3.         print('testing...')

  4.        
  5. >>> test()
  6. 进入装饰器...
  7. testing...
  8. 离开装饰器...
复制代码


可以得知,装饰器参数中的 func 在这里就是 test。装饰器其实等同于:

  1. >>> def test():
  2.         print('testing...')

  3.        
  4. >>> test = deco(test)
  5. >>> test()
  6. 进入装饰器...
  7. testing...
  8. 离开装饰器...
复制代码


但是,细心的鱼油会发现,装饰器在一定程度上会破坏函数本身:

  1. >>> print(test.__name__)    # 应该是 'test'
  2. wrapper
复制代码


我们可以用 functools.wraps 装饰器解决这个问题:

  1. >>> from functools import wraps
  2. >>> def deco(func):
  3.         @wraps(func)
  4.         def wrapper(*args, **kwargs):
  5.                 print("进入装饰器...")
  6.                 func(*args, **kwargs)
  7.                 print("离开装饰器...")
  8.         return wrapper

  9. >>> @deco
  10. def test():
  11.         print('testing...')

  12.        
  13. >>> test()
  14. 进入装饰器...
  15. testing...
  16. 离开装饰器...
  17. >>> print(test.__name__)
  18. test
复制代码


学会了自定义简单的装饰器之后,我们可以编写一个计量代码用时的装饰器:

  1. >>> import time
  2. >>> def timeit(func):
  3.         @wraps(func)
  4.         def wrapper(*args, **kwargs):
  5.                 start = time.perf_counter()
  6.                 func(*args, **kwargs)
  7.                 print('用时', time.perf_counter() - start, '秒')
  8.         return wrapper
复制代码


测试:

  1. >>> @timeit
  2. def test():
  3.         s = 0
  4.         for i in range(10000):
  5.                 s += i

  6.                
  7. >>> test()
  8. 用时 0.00043929999992542434 秒
复制代码

本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-1-30 13:38:25 | 显示全部楼层
嗯,没有任何人回复
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-23 13:20:10 | 显示全部楼层
学习到了^_^
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-11 10:27

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表