为什么用装饰器?
- 第一个原因是,使用装饰器可以提升代码复用,避免重复冗余代码。如果我有多个函数需要测量执行时间,我可以直接将装饰器应用在这些函数上,而不是给多个函数加上一样的代码。这样的代码既元余也不方便后面维护
- 第二个原因是,使用装饰器可以保证函数的逻辑清晰。如果一个本身功能就很复杂的函数,我还要通过修改内部代码来测量运行时间,这样会模糊函数自身的主逻辑。同时,软件开发的一个原则就是单一职责,也就是说,一个函数只应该承担一项责任
- 第三,通过装饰器,我们可以扩展别人的函数。想象我们正在使用一个第三方库的函数,但我要添加额外的行为,比如测量运行时间,那我就可以用装饰器去包装,而不是跑到库里面去修改。
import time
import math
#函数接收的参数为函数
def mysqrt(x):
return math.sqrt(x)
def print_running(f,x):
print(f'{f.__name__} is running')
return f(x)
result= print_running(mysqrt,9)
print(result)
mysqrt is running
3.0
#基本的装饰器例子
import time
def myDecorator(func):
def warpper(*args,**kwargs):
start_time=time.time()
result=func(*args,**kwargs)
end_time=time.time()
print(f'{func.__name__} running time :{end_time-start_time}')
return result
return warpper
dec_mysqrt=myDecorator(mysqrt)
result=dec_mysqrt(9)
print(result)
#使用@语法完成函数名字上面代码段的dec_mysqrt=myDecorator(mysqrt)替换
@myDecorator#函数接收的参数为函数
def mysqrt(x):
return math.sqrt(x)
x=mysqrt(10)
print(x)
mysqrt running time :0.0
3.0
#装饰器生成器:比如要要测量某函数运行时间是否超过阈值,但不同函数的阈值是不一样的,所以需要定义多个装饰器应对不同阈值吗?不,只需要用装饰器生成器
def timer(threshold):
def decorator(func):
def warpper(*args,**kwargs):
start_time=time.time()
result=func(*args,**kwargs)
end_time=time.time()
if (end_time-start_time>threshold):
print(f'{func.__name__} running time is over {threshold} seconds')
return result
return warpper
return decorator
@timer(0.2)
def sleep_04():
time.sleep(0.4)
# #上述写法的等价写法
# def sleep_04():
# time.sleep(0.4)
# sleep_04 =timer(0.2)(sleep_04)
sleep_04()
print(sleep_04.__name__)
sleep_04 running time is over 0.2 seconds
warpper
#但是上面的代码的sleep_04.__name__是warpper,不是sleep_04。
#能继承函数名字等参数的装饰器生成器
import functools
def timer(threshold):
def decorator(func):
@functools.wraps(func)
def wrapper(*args,**kwargs):
start_time=time.time()
result=func(*args,**kwargs)
end_time=time.time()
if (end_time-start_time>threshold):
print(f'{func.__name__} running time is over {threshold} seconds')
return result
return wrapper
return decorator
@timer(0.2)
def sleep_04():
time.sleep(0.4)
# #上述写法的等价写法
# def sleep_04():
# time.sleep(0.4)
# sleep_04 =timer(0.2)(sleep_04)
sleep_04()
print(sleep_04.__name__)
sleep_04 running time is over 0.2 seconds
sleep_04