1、概念
装饰器(Decorator)用于在不改变原有函数的前提下,添加额外的功能。例如记录日志等。
装饰器本质上就是一个返回函数的高阶函数。
Tips:如果你了解Spring Framework的话,那么你可以对比着AOP来理解Python的装饰器
2、语法
使用Python的 @ 语法糖,将装饰器定义于函数的定义处
def decorator(fn):
def wrapper(*args, **kw)
return fn(*args, **kw)
return wrapper
@decorator
def fn(x):
pass
3、示例
def log(fn):
def wrapper(*args, **kw):
fnName = fn.__name__
print('【%s】方法开始执行' %(fnName))
try:
result = fn(*args, **kw)
print('【%s】方法返回值:%s' %(fnName, str(result)))
return result
except Exception as e:
print('【' + fnName + '】方法执行异常', e)
finally:
print('【%s】方法执行完毕' %(fnName))
return fn(*args, **kw)
return wrapper
def log2(fn):
def wrapper(*args, **kw):
fnName = fn.__name__
print('--- 【%s】方法开始执行 ---' %(fnName))
try:
result = fn(*args, **kw)
print('--- 【%s】方法返回值:【%s】 ---' %(fnName, str(result)))
return result
except Exception as e:
print('--- 【' + fnName + '】方法执行异常', e, ' ---')
finally:
print('--- 【%s】方法执行完毕 ---' %(fnName))
return wrapper
@log2
@log
def my_fn(x):
x = int(x)
if (0 < x):
return x
elif (0 == x):
return 0
else:
return -x
def main():
x = input('请输入:')
result = my_fn(x)
print('结果为:%d' %(result))
if __name__ == '__main__':
main()
这里定义了2个装饰器,并置于 my_fn 函数的定义处
可以看到执行 my_fn 函数,会打印出对应的装饰器的日志信息
4、总结
如果有多个装饰器,则会先执行最上定义的装饰器的方法执行前的代码,然后按照顺序执行剩下的装饰器的代码
示例:
@log3
@log2
@log
def fn(*args, **kw):
pass
执行顺序:
- log3的执行 fn 方法前的代码
- log2的执行 fn 方法前的代码
- log的执行 fn 方法前的代码
- log执行 fn 代码
- log的执行 fn 方法后的代码
- log2执行 fn 代码
- log2的执行 fn 方法后的代码
- log3执行 fn 代码
- log3的执行 fn 方法后的代码