Python 装饰器
python装饰器
装饰器用一句话解释,就是python闭包函数的一种语法糖,用来对函数进行辅助。
闭包本身是一个函数,其传入参数和返回值都是函数,有点切面编程的工厂设计模式的意思在里边感觉。
现在我们由浅入深来实现一个python装饰器的使用场景,并引出装饰器。
实现一个功能,记录查找1到100中奇数这个函数的执行时间。
1. 原始方法
import time
def print_odds():
start_time = time.perf_counter()
for i in range(100):
if i % 2 != 0:
print(i)
end_time = time.perf_counter()
print(f'运行总时间为{end_time - start_time}')
if __name__ == '__main__':
print_odds()
缺点:函数主要逻辑不突出,辅助功能在函数内部占用地方,不利于维护。
2. 拆分主要函数和辅助函数
import time
def count_time(func):
start_time = time.perf_counter()
func()
end_time = time.perf_counter()
print(f'运行总时间为{end_time - start_time}')
def print_odds():
for i in range(100):
if i % 2 != 0:
print(i)
if __name__ == '__main__':
count_time(print_odds)
这样写的话主函数功能逻辑和辅助函数就能够解耦合了,但是对外调用的接口是辅助函数,不利用使用者使用。
3. 函数闭包
import time
# 闭包函数,本质是一个函数,传入和返回都是函数
def count_time(func):
def improve_func():
start_time = time.perf_counter()
func()
end_time = time.perf_counter()
print(f'运行总时间为{end_time - start_time}')
return improve_func
def print_odds():
for i in range(100):
if i % 2 != 0:
print(i)
if __name__ == '__main__':
print_odds = count_time(print_odds)
print_odds()
这样做的话是不是就解决了上面第2点说的缺点,这里用到的就是闭包函数,这里要注意的点就是函数作为参数和返回的时候都是不加括号的。
但是这样写还是不够简洁,而且需要提前显式调用闭包函数对函数进行增强。
4. 装饰器
import time
def count_time(func):
def improve_func():
start_time = time.perf_counter()
func()
end_time = time.perf_counter()
print(f'运行总时间为{end_time - start_time}')
return improve_func
@count_time
def print_odds():
for i in range(100):
if i % 2 != 0:
print(i)
if __name__ == '__main__':
print_odds()
装饰器增强只增强一次,且在第一次调用时增强。
通用的装饰器
def general_wrapper(func):
def wrapper(*args,**kwargs):
ret = func(*args,**kwargs)
return ret
return wrapper
5. 有参数的装饰器
import time
def count_time(param):
print(param)
def improve_func(func):
def wrapper(*args,**kwargs):
start_time = time.perf_counter()
func(*args,**kwargs)
end_time = time.perf_counter()
print(f'运行总时间为{end_time - start_time}')
return wrapper
return improve_func
@count_time(123)
def print_odds(lim = 100):
for i in range(lim):
if i % 2 != 0:
print(i)
if __name__ == '__main__':
print_odds()
License:
CC BY 4.0