装饰器
在调用函数时,可以对一些重复的功能进行包装。例如,当计算一个函数的运行时间时,需要记录开始调用的时刻和返回的时刻,并进行相减得到时间。如果重复进行多次,则需要做多个这种操作。为了简化这一过程,可使用装饰器。
def timmer(func):
def wrapper():
start_time = time.time()
func()
stop_time = time.time()
print("运行时间是 %s 秒 " % (stop_time - start_time))
return wrapper
@timmer
def wait():
time.sleep(3)
# 调用
wait()
其中,timmer()
采用了函数闭包的形式。
这里的 @
是称为语法糖,相当于 wait = timmer(wait)
语句。当调用 wait()
函数时,首先去调用 timmer()
函数,并把 wait()
函数传递进去,返回一个 wrapper()
函数对象给 wait 变量。此举也简化了函数闭包的调用过程。
总结一下,装饰器的目的就是进行一些额外操作。比如在这个例子中,最核心的部分就是 wait()
函数,但是想要在 wait()
函数外进行一些额外操作就可以用到装饰器,在这个例子中就是记录开始时间、结束时间并打印用时。
在上面的例子中,wait()
函数并没有参数,下面通过一个计算和的例子来说明带参数的情况。
def tips(func):
def sum(a, b):
print('a + b')
func(a, b)
return sum
@tips
def add(a, b):
print(a + b)
# 调用
add(4, 5)
当装饰器带上了参数可以做更多的事情,如
def tips(argv):
def f(func):
def add_or_sub(a, b):
print(argv)
func(a, b)
return add_or_sub
return f
@tips('add')
def add(a, b):
print(a + b)
@tips('sub')
def sub(a, b):
print(a - b)
# 调用
add(6, 2) # add 8
sub(6, 2) # sub 4