Python 装饰器本身就是一个函数,它的作用是装饰一个其他的函数,但是不改变原有的程序功能,还要增添新的功能,调用函数时的接口没有变化。比如,装修一个房子,如果不隔音,我在墙上加一层隔音板,却不能把墙拆了,换成隔音材质。
import time #导入时间模块
def index():
time.sleep(2) #时间休眠2秒
start_time = time.time() #time.time 是时间戳,指北京时间19700101 080000 起至现在的总毫秒数
index()
end_time = time.time()
print(end_time - start_time) #2.0136349201202393
虽然完成了计时功能,但如果函数有非常多个,那每一个函数的计时都要定义开始时间和结束时间的变量,比较繁琐。
import time #导入时间模块
def index():
time.sleep(2) #时间休眠2秒
def calculate_time(f):
start_time = time.time()
f()
end_time = time.time()
print(end_time - start_time)
calculate_time(index) #2.0035324096679688
但装饰器不改变原有的函数调用接口,之前的函数是index 而现在要写上calculate_time(index),这样也是很不方便的。比如玩家在玩游戏时通常用WASD来控制上下左右,有一天如果改成了CSAV来控制,肯定就会有很多玩家放弃这个游戏,因此我们需要进一步升级程序。
import time #导入时间模块
def index():
time.sleep(2) #时间休眠2秒
def calculate_time(f):
def inner():
start_time = time.time()
f()
end_time = time.time()
print(end_time - start_time)
return inner
index = calculate_time(index)
index() #2.0142064094543457
这样,既可以不改变接口又可以成功运行程序。
在用装饰器之前还要写上 index = calculate_time(index) 这样一行代码,显然是很不方便的。这时候可以用 @calculate_time 替换 index = calculate_time(index)
import time #导入时间模块
def calculate_time(f):
def inner():
start_time = time.time()
f()
end_time = time.time()
print(end_time - start_time)
return inner
@calculate_time # 等价于index = calculate_time(index) 这行赋值的代码
def index():
time.sleep(2.2) #时间休眠2.2秒
index() #2.2051877975463867
举例
import time
def timer(func):
'''统计函数运行时间的装饰器'''
def wrapper():
start = time.time()
func()
end = time.time()
used = end - start
print(f'{func.__name__}used{used}')
return wrapper
@timer
def step1():
print('step1.....')
@timer
def step2():
print('step2.....')
@timer
def step3():
print('step3.....')
step1()
step2()
step3()