装饰器
- 装饰器实际上就是为了给某程序增添功能,但该程序已经上线或已经被使用,那么就不能大批量的修改源代码,这样是不科学的也是不现实的,因为就产生了装饰器,使得其满足:
- 不能修改被装饰的函数的源代码
- 不能修改被装饰的函数的调用方式
- 满足1、2的情况下给程序增添功能
那么根据需求,同时满足了这三点原则,这才是我们的目的。因为,下面我们从解决这三点原则入手来理解装饰器。
-
< 函数+实参高阶函数+返回值高阶函数+嵌套函数+语法糖 = 装饰器 >
例子:
import time
def test():
time.sleep(2)
print("test is running!")
test()
添加功能:统计运行时间(2 second)功能
import time
def test():
time.sleep(2)
print("test is running!")
def deco(func):
start = time.time()
func() #2
stop = time.time()
print(stop-start)
deco(test) #1
换为闭包写法
import time
def timer(func) #5
def deco():
start = time.time()
func()
stop = time.time()
print(stop-start)
return deco
def test():
time.sleep(2)
print("test is running!")
if __name__=="__main__":
test = timer(test) #6
test() #7
真正的装饰器
根据以上分析,装饰器在装饰时,需要在每个函数前面加上:
test = timer(test)
- 显然有些麻烦,Python提供了一种语法糖,即:
@timer
- 这两句是等价的,只要在函数前加上这句,就可以实现装饰作用。
以上为无参形式
无参数
import time
def timer(func)
def deco():
start = time.time()
func()
stop = time.time()
print(stop-start)
return deco
@timer
def test(parameter): #8
time.sleep(2)
print("test is running!")
test()
有参数
import time
def timer(func)
def deco(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
stop = time.time()
print(stop-start)
return deco
@timer
def test(parameter): #8
time.sleep(2)
print("test is running!")
test()
如果原函数有返回值
def test(parameter):
time.sleep(2)
print("test is running!")
return "Returned value"
import time
def timer(func)
def deco(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
stop = time.time()
print(stop-start)
return res
return deco
@timer
def test(parameter): #8
time.sleep(2)
print("test is running!")
return "Returned value"
test()
传参数
import time
def timer(parameter):
def outer_wrapper(func):
def wrapper(*args, **kwargs):
if parameter == 'task1':
start = time.time()
func(*args, **kwargs)
stop = time.time()
print("the task1 run time is :", stop - start)
elif parameter == 'task2':
start = time.time()
func(*args, **kwargs)
stop = time.time()
print("the task2 run time is :", stop - start)
return wrapper
return outer_wrapper
@timer(parameter='task1')
def task1():
time.sleep(2)
print("in the task1")
@timer(parameter='task2')
def task2():
time.sleep(2)
print("in the task2")
task1()
task2()
网友评论