Python装饰器本质上是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器返回的值也是一个函数对象。
它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计。
python提供了@符号作为装饰器的语法糖,使我们更方便的应用装饰函数。但使用语法糖要求装饰函数必须return一个函数对象。
我们下来举一个例子:
比如我们要获取一个函数的运行时间:
# -*- coding:utf-8 -*-
from time import sleep, time
from random import randint
def main_test1():
start_time = time()
for i in range(10):
print('执行结果 %s' % i)
sleep(randint(2, 5))
end_time = time()
print('执行总时间:%s秒' % (end_time - start_time))
if __name__ == '__main__':
main_test1()
通过结束时间减去开始时间获取执行的时间,但是如果我们有N多个方法里都要获取执行时间,就需要每个方法里都去写一遍,这时候我们可是通过装饰器来实现这已功能:
def run_time(func):
def main():
start_time = time()
func()
end_time = time()
print('执行总时间:%s秒' % (end_time - start_time))
return main
@run_time
def main_test2():
for i in range(10):
print('执行结果 %s' % i)
sleep(randint(2, 5))
if __name__ == '__main__':
main_test2()
装饰器通过@符实现,在需要执行的方法上定义执行函数,相当于把 main_test2() 函数作为参数传递给 run_time() 函数:run_time(main_test2)
通过装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。
装饰器传递参数
def run_time(func):
def main(a='', b=''):
print(a, b)
func(a, b)
return main
@run_time
def main_test2(a='', b=''):
print(a, b)
if __name__ == '__main__':
main_test2('aaaa', 'bbbb')
需要注意的是参数记得使用默认值或者使用不定长传参,如果变量不传递参数又没有默认值,方法会报错
另外在 func 方法调用的时候记得把参数回传。