Python装饰器应用于日志输出

2018-11-19  本文已影响74人  dnsir

1 入门

装饰器应该是Python里面最难理解的概念了,网络很多文章和教程都试图把装饰器讲的很明白,其实是讲明白了,但对于没有实际项目开发经验的人来说装饰器不容易掌握,且在日常业务开发中,尽快将业务开发完成上线才是首要任务,代码质量往往成为其次,偶尔闲来需要不断补充新的知识而不是细细品味已经上线的代码。

2 函数装饰器

既然是装饰,那么就是在函数真正执行之前(或者之后)进行一些装饰(包裹),装饰可以对函数的输入参数,也可以在函数运行之前进行一些操作,也可以在函数运行之后进行一些操作,装饰器只是一个语法糖语法糖,就是这样写就是这样的结果,为什么是这样的结果?没有为什么)。

3 接近实际的例子

以日志输出为例,在日志系统设计中,往往会设计如下几个函数:

def debug(msg):
    msg = "debug " + msg
    print(msg)

def info(msg):
    msg = "info " + msg
    print(msg)

如果有很多日志级别如error,warn,trace等,那么msg = "debug" + msg将会重复又重复,这个时候装饰器是可以派上用场,如之前所说,装饰器可以在函数执行之前对参数进行一些操作,这里主要就是对输入参数msg进行操作,突然感觉装饰器也有点类似C++的模板,方便代码复用,当然这也是装饰器的重要意义。

4 使用装饰器

使用装饰器将提取一个wrapper函数(包裹函数),使用语法糖@do_log完成装饰器的使用。

from functools import wraps

def do_log(func):
    @wraps(func)
    def wrapper(*args, **kw):
        if func.__name__ == "debug":
            msg = "debug {}".format(args[0])
        elif func.__name__ == "info":
            msg = "info {}".format(args[0])
        else:
            msg =  "unknown {}".format(args[0])
        return func(msg, **kw)
    return wrapper

@do_log
def debug(msg):
    print(msg)

@do_log
def info(msg):
    print(msg)

if __name__ == "__main__":
    debug("123")
    info("abc")

当然这个例子还有许多地方值得完善,比如参数直接使用了args[0]等,其实装饰器只是帮我们做了一件事情,即通过语法糖实现了 debug = do_log(debug),然后debug("123"),执行的是wrapper("123")。当然实际实现会比这里所说的略微复杂,但是大体如此。

5 总结

装饰器虽然是Python的重要语法糖,但是阅读开源代码来看使用没有那么普通,上述例子通过函数封装可以实现同样的工作,除非是已经习惯装饰器这种语法糖。

上一篇下一篇

猜你喜欢

热点阅读