
有函数如下,如何在不破坏函数的情况下为函数增加输出日志功能?
def say_nihao():
print('nihao')
很简单,我们只需要对函数进行封装即可
def log()
print('我是日志')
say_nihao()
现在我们只需要调用log()函数即可,相信很多人都是这样写的,但是这样写有很大的弊端。
- 我们需要找到程序中所有调用say_nihao()的地方改成log()如果现在又有一个函数say_hello()也需要增加输出日志功能,我们岂不是要再来一遍?也就是说我们刚才的 *** 作是不能复用的
下面我们来介绍python中的装饰器。
对于第一个问题,我们这样进行修改:
def log()
print('我是日志')
return say_hello
say_nihao=log()
要解决第二个问题,我们只要把函数当作参数传递进去就可以了
def log(func)
print('我是日志')
return func
say_nihao=log(say_nihao)
这样我们就不需要修改程序,并且代码可以复用,而log()我们称作装饰器。
我们通常将装饰器中增加的功能使用wrapper()包装起来,此时我们执行say_nihao()就相当于执行wrapper()
def log(func)
def wrapper():
print('我是日志')
return func
return wrapper
say_nihao=log(say_nihao)
在面向切面编程(AOP)中,我们将log()称为切面。将切面和具体函数结合的地方,也就是say_nihao=log(say_nihao)称为切入点。
如果say_nihao()函数有参数 ,我们可以这样:
def log(func)
def wrapper(*args, **kwargs):
print('我是日志')
return func(*args, **kwargs)
return wrapper
say_nihao=log(say_nihao)
*args和**kwargs作用不在说明。
在python中为say_nihao=log(say_nihao)提供了一种语法糖:@
def log(func)
def wrapper(*args, **kwargs):
print('我是日志')
return func(*args, **kwargs)
return wrapper
@log
def say_nihao():
print('nihao')
这里说一下参数的问题,如果@log没有参数,那么传递到装饰器log()函数里的是say_nihao对象,如果@log(a)有参数,那么那么传递到装饰器log()函数里的是@log(a)里面的参数a,而say_nihao对象将被传递到wrapper()函数里。
基于此,如果装饰器本身需要参数,那么可以这么些:
def log(value):
def decorator(func):
def wrapper(*args, **kwargs)
print(value)
return func(*args, **kwargs)
return wrapper
return decorator
@log('我是日志')
def say_nihao():
print('nihao')
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)