思路源自于 BV1SZ4y1s7cv
闭包与装饰器
假如要实现一个功能,包含了两个功能,一个是计算运行的时间,一个是计算奇数,那么可以这样实现:
def index():
start_time = time.time()
for i in range(10000):
if i % 2 == 1:
print(i)
end_time = time.time()
timex = end_time - start_time
print("it takes " + str(timex))
if __name__ == "__main__":
index()
那么这两个功能就会变得耦合,那么就要将其分离为两个函数,应使用闭包:
def count_time_wrapper(func):
# 闭包,用于增强函数func,给函数func增加统计时间的功能
def improved_func(*args,**kwargs):
start_time = time.time() # 当前时间
odd = func(*args,**kwargs)
end_time = time.time()# 当前时间
print("it takes " + str(end_time-start_time)) # 执行func消耗的时间
return odd
return improved_func
def print_odds(lim = 1000):
sum = 0
for i in range(lim):
if i%2 == 1:
sum += 1
return sum
if __name__ == "__main__":
print(count_time_wrapper(print_odds).__name__) # improved_odds
print(print_odds =count_time_wrapper(print_odds)(lim = 10000))
"""
最终运行结果为:
improved_func
it takes 0.0009989738464355469
5000
"""
其中count_time_wrapper(print_odds)得到的是improved_func函数,并且已经传入了print_odds函数作为参数,后面加上去(lim = 10000)表示执行了improved_func(print_odds)。这样做的好处在于两个功能分为了两个函数。
假如在print_odds函数上面加上装饰器,如下:
def count_time_wrapper(func):
# 闭包,用于增强函数func,给函数func增加统计时间的功能
def improved_func(*args,**kwargs):
start_time = time.time() # 当前时间
odd = func(*args,**kwargs)
end_time = time.time()# 当前时间
print("it takes " + str(end_time-start_time)) # 执行func消耗的时间
return odd
return improved_func
@count_time_wrapper # 装饰器
def print_odds(lim = 1000):
sum = 0
for i in range(lim):
if i%2 == 1:
sum += 1
return sum
if __name__ == "__main__":
"""
print_odds 上了装饰 器 @count_time_wrapper 后,等价于在第一次调用函数时执行了以下语句:
print_odds =count_time_wrapper(print_odds)
"""
print(count_time_wrapper(print_odds).__name__)
print(print_odds(lim = 10000))
"""
最终运行结果为:
improved_func
it takes 0.0009989738464355469
5000
"""
也就是说加上去装饰器后第一次执行print_odds(lim = 10000)相当于执行了print_odds =count_time_wrapper(print_odds) ,相当于是增强了print_odds函数的功能,后面再使用print_odds(lim = 10000)时就不会在增强了,也就是说只增强一次。
多重装饰器
def wrapper1(fun):
print("this is 1")
def callback():
print("this is 1 callback")
fun()
return callback
def wrapper2(fun):
print("this is 2")
def callback():
print("this is 2 callback")
fun()
return callback
@wrapper1
@wrapper2
def wrapper3():
print("this is 3")
if __name__ == "__main__":
# 第一次执行了wrapper3 = wrapper1(wrapper2(wrapper3))
wrapper3()
print("----")
# 后面就不再进行增强,也就是不执行wrapper3 = wrapper1(wrapper2(wrapper3)),因为第一次已经执行过了
wrapper3()
"""
结果:
this is 2
this is 1
this is 1 callback
this is 2 callback
this is 3
----
this is 1 callback
this is 2 callback
this is 3
"""