defdo_get():print('do get')logging.info('go get logging')
但是如果我们要给类似的函数都加上函数的执行日志,会造成大面积的修改,如果一两个函数还是可以的
但是如果有很多的函数需要添加,就需要大量的工作,这个是不可取的
所以需要一个专门来处理日志的函数
1
2
3
4
5
6
7
8
9
10
11
importloggingdefdo_logging(func):logging.warning(f"{func.__name__} is running")func()defdo_get():print("do get")do_logging(do_get)
但是这样的话,需要每次将一个函数作为参数传递给do_logging函数,也不是非常理想
于是我想到了装饰器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
importloggingdefdo_logging(func):defwrapper(*args,**kwargs):logging.warning(f"{func.__name__} is running")returnfunc(*args,**kwargs)returnwrapperdefdo_get():print('do get')do_get=do_logging(do_get)do_get()
这里do_logging就是一个装饰器
'@符号'是装饰器的语法糖,在定义函数的时候使用,避免再一次赋值操作,使用方式如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
importloggingdefdo_logging(func):defwrapper(*args,**kwargs):logging.warning(f"{func.__name__} is running")returnfunc(*args,**kwargs)returnwrapper@do_loggingdefdo_get():print('do get')do_get()
使用装饰器极大地复用了代码,但是他有一个缺点就是原函数的元信息不见了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
importloggingfromfunctoolsimportwrapsdefdo_logging(func):@wraps(func)defwrapper(*args,**kwargs):logging.warning(f"{func.__name__} is running")func(*args,**kwargs)returnwrapper@do_loggingdefdo_get():print('do get')do_get()