Python函数修饰符@的作用是为现有的函数增加额外的功能;其作用非常强大,今天我们就来谈谈它是如何在日志记录中起到很好的作用的。

先看一个例子

log是一个日志函数,当程序运行于DEBUG模式下时,用于记录函数运行的开始时间,和结束时间。

可是这段代码有个弊端,在测试某个参数时,我们需要,添加类似于log(test)这样的代码,不需要后把它删除;这样做很麻烦。

很幸运,我们有@函数修饰符。修改下上面的代码,删除 log(test) 这行代码

在test函数的上方加入 @log 装饰器

这段代码和上述代码功能是一样的。

可是问题又来了;运行上述代码,发现我们没有调用 test 函数,test就已经被执行了。因为 @log 等于 log(test)。修改代码:

我们在log函数中定义了一个wrapper函数,并将这个函数返回

相当于 log(test) ,而调用log后,test函数不会被立即执行,而是把test进行再次包装,返回这个再包装的函数地址。

需要这样才能让函数运行

在使用@log装饰器后,直接调用test()即可自动获取函数运行日志,我们可以为很多需要测试的函数添加@log装饰器,不需要直接将__DEBUG__设置成 False

在使用装饰器后,test函数变成了wrapper函数

上图为 print(test)的运行效果。

可能很多人看到这里还是一知半解,它的执行顺序是这样的。

运行 test(使用了@log装饰器)函数后,首先被执行的是log函数,log函数定义一个wrapper函数,并返还给test(使用了@log装饰器),此时test函数就是wrapper函数。

替换过程完成。

此时我们再调用test函数(已经被替换成wrapper),wrapper函数打印运行记录,并执行test函数(这里的test函数是最原始的test)

如何给函数添加参数

有这样的情节

先修改上文代码test()函数

这种情况我们应该怎么修改wrapper呢

其实我们了解整个执行流程后,就已经很清楚了,只需这样修改

*args是将参数以元组的形式打包成tuple给函数体调用

**kwargs是将关键字参数打包成dict给函数体调用

本文不对这两种参数打包形式进行细说,作者今后会另写一篇文章来细说,欢迎关注。

test函数使用参数的问题已经解决,那么@log装饰器又该怎么添加参数呢?

为@log装饰器添加参数

有这种应用场景

怎么能让装饰器拥有参数呢?

很简单,只需要再次包装

其中原理和前面提到的test函数被替换的概念是一样的。

为@log装饰器添加方法

又有这样的场景

我现在希望添加一个方法,让其功能更加丰富。

那么log函数有点虚脱了,虽有有方法在log函数中实现这一目的,但是有一种更简单的方法,那就是使用类:

使用前别忘记实例化

这就实现了前面的方法

现在只需要在 _log类中定义方法,即可像@log装饰器添加方法

具体的sendto功能就不写了。

完整源码

本文首发于百家号 :http://baijiahao.baidu.com/builder/preview/s?id=1644581893902732381

hocoding.com 保留所有权;如需转载,请注明出处。

发表评论

电子邮件地址不会被公开。 必填项已用*标注