Python编写装饰器,给任意函数计时
蚂蚁学Python
共 1767字,需浏览 4分钟
·
2021-05-21 23:03
在开发代码时,经常有这样的需求,想知道调用一个函数的入参、返回值、花费时间。
对应这个调用,我们可以自己在函数开头打印参数、末尾打印结果、结尾时间减去开始时间计时。
然而这样的代码,其实任何函数都一样,有没有办法写一次代码多次调用呢。
这其实就是“给任何函数,增加一个公共的附加特性”,可以用Python的解释器解决。
# 1、导入相关的包
import functools
import logging
import time
log_format = "%(asctime)s %(message)s"
logging.basicConfig(format=log_format,
level=logging.INFO)
这用到了functools包,它有wraps方法,是装饰需要的函数。
# 2、编写装饰器
def time_logger(func):
def wrapper_timer(*args, **kwargs):
logging.info(f"BeginFunction {func.__name__!r}, args={args}, kwargs={kwargs}")
start_time = time.perf_counter() # 1
value = func(*args, **kwargs)
end_time = time.perf_counter() # 2
run_time = end_time - start_time # 3
logging.info(f"EndFunction {func.__name__!r} in {run_time:.4f} secs")
return value
return wrapper_timer
大家注意,这个装饰器会被任何函数使用。其中的func(*args, **kwargs)中的func就是目标函数,args、kwargs是这个函数调用的参数。
这就实现了一个装饰器。
# 3、使用装饰器给函数计时
def my_func(name, age):
logging.info(f"my func begin, {name}, {age}")
time.sleep(2)
logging.info(f"my func end, {name}, {age}")
@time_logger就是计时器的装饰器使用方式,任何函数只需要这个简单地一行代码,就可以加上这个功能。
# 4、我们来看看调用效果
执行如下代码:
my_func("antpython", "99")
打印结果为:
2021-05-17 20:30:26,294 BeginFunction 'my_func', args=('antpython', '99'), kwargs={}
2021-05-17 20:30:26,294 my func begin, antpython, 99
2021-05-17 20:30:28,295 my func end, antpython, 99
2021-05-17 20:30:28,295 EndFunction 'my_func' in 2.0007 secs
其中第一行BeginFunction、最后一行EndFunction,都是装饰器里面的输出。
而my func begin、my func end,则是自己的函数的输出。
# 5、最后的总结
对于装饰器,可以有很多用途:
WEB服务中检测用户是否登录
加入所有函数的日志、计时功能
对所有访问数据库的函数加上入侵检测功能
对用户的访问请求做攻击检测
自动处理数据库的链接提取、提交、回滚等操作
只要是一个通用的功能,都可以用装饰器来解决。这在其他语言比如JAVA中也叫做拦截器、代理等功能。
这是一个很有用的特性,赶快试试吧!
评论