如何实现一个python函数装饰器(Decorator)

作者:半杯茶的小酒杯 时间:2023-12-02 19:38:37 

装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象。它经常用于为已有函数/类添加记录日志、计时统计、性能测试等。

首先定义一个倒计时函数,这个函数的功能非常简单,就是把n从当前值减少到0。


def countdown(n):
while n > 0:
 print('time' + str(n))
 n -= 1

print(countdown.__name__)

程序输出:

countdown

1.为函数增加一个日志装饰器

假设现在要增强countdown的功能,在函数调用前后自动打印日志,又不想修改函数自身的功能。这种在代码运行期间动态增加功能的方式,称之为装饰器(Decorator)。

能打印日志的decorator,可以定义如下:


def log(func):
 def wrapper(*args, **kw):
   print('call %s().' % func.__name__)
   return func(*args, **kw)
 return wrapper

然后我们借助Python的@语法,把decorator置于函数的定义处:


@log
def countdown(n):
while n > 0:
 print('time:' + str(n))
 n -= 1

countdown(10)

程序输出:

call countdown().
time:10
time:9
time:8
time:7
time:6
time:5
time:4
time:3
time:2
time:1

但此时我们再打印函数的name:


print(countdown.__name__)

程序输出:

wrapper

我们发现函数的元数据信息变了,这显然不是我们想要的结果。

2. 在装饰器中拷贝元数据

为了把函数的元数据信息都保留下来,我们可以直接使用Python提供的functools库中的@wraps装饰器。


from functools import wraps

def log(func):
 @wraps(func)
 def wrapper(*args, **kw):
   print('call %s().' % func.__name__)
   return func(*args, **kw)
 return wrapper

@log
def countdown(n):
while n > 0:
 print('time:' + str(n))
 n -= 1

print(countdown.__name__)

程序输出:

countdown

3.为函数增加一个计时装饰器

添加函数装饰器的方法已经讲清楚了,现在再实现一个完整的函数计时耗时装饰器。


import time
from functools import wraps

def TimeCost(func):
@wraps(func)
def wrapper(*arg, **kwargs):
 start = time.time()
 result = func(*args, **kwargs)
 end = time.time()
 print(func.__name__, end - start)
 return result
return wrapper

@TimeCost
def countdown(n):
while n > 0:
 print('time:' + str(n))
 n -= 1

countdown(10000)

函数输出:

('countdown', 0.0004801750183105469)

参考资料:

https://www.liaoxuefeng.com/wiki/1016959663602400/1017451662295584

Python Cookbook中文版

来源:http://www.banbeichadexiaojiubei.com/index.php/2020/10/11/%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AApython%E5%87%BD%E6%95%B0%E8%A3%85%E9%A5%B0%E5%99%A8decorator/?utm_source=tuicool&utm_medium=referral

标签:python,函数,装饰器,Decorator
0
投稿

猜你喜欢

  • python连接sql server乱码的解决方法

    2023-06-27 07:25:17
  • python: 自动安装缺失库文件的方法

    2023-08-30 05:42:38
  • Python 如何写入Excel格式和颜色

    2023-03-10 20:49:55
  • 基于Python实现英语单词小游戏

    2023-03-22 01:34:19
  • 安装PHP可能遇到的问题“无法载入mysql扩展” 的解决方法

    2023-09-09 04:37:39
  • JavaScript事件委托技术实例分析

    2023-07-01 01:18:23
  • python线程、进程和协程详解

    2023-03-02 14:00:39
  • python实现excel公式格式化的示例代码

    2021-08-09 17:27:52
  • Python制作词云的方法

    2021-08-26 19:52:20
  • 使用python的pexpect模块,实现远程免密登录的示例

    2022-10-19 18:30:22
  • Python中的数学运算操作符使用进阶

    2021-05-24 16:05:46
  • linux安装Python3.4.2的操作方法

    2022-06-17 19:19:15
  • 儿童编程python入门

    2021-03-12 15:25:06
  • layui点击按钮页面会自动刷新的解决方案

    2024-04-18 09:33:11
  • 基于Python函数和变量名解析

    2022-10-26 13:49:56
  • javascript hasFocus使用实例

    2024-04-10 10:57:41
  • 解析:校对确定 较为复杂的一些特殊情况

    2008-12-17 16:54:00
  • int在python中的含义以及用法

    2023-07-28 08:48:21
  • SQL Server如何实现快速删除重复记录?

    2011-05-03 11:18:00
  • 带你一文读懂Python垃圾回收机制

    2022-03-03 11:58:03
  • asp之家 网络编程 m.aspxhome.com