概念
装饰器(Decorators)是 Python 的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短,也更Pythonic(Python范儿)。
作用
假设我们有这么一个需求:计算一个函数运行的时间
你可能会这么写:
# 普通求取函数执行时间的方法
def get_time():
start = time.time()
sum = 0
for i in range(1000000):
sum = sum + i
print(sum)
end = time.time()
print(f"full time:{(end - start)}")
但我可能需要计算很多个函数的时间,这样插入语句会很麻烦,重复的工作总是让人感觉厌烦,而且当我的项目做完后,并不想要这些测试代码,我还得再次花时间删除他们。
所以有了简便的方法:装饰器
# 运用装饰器
def decorator_time(func):
def wrapper():
start = time.time()
func()
end = time.time()
print(f"decorator full time:{(end - start)}")
return wrapper
@decorator_time
def get_sum1():
sum = 0
for i in range(100000):
sum = sum + i
print(sum)
if __name__ == "__main__":
get_sum1(100000)
你可以这么理解:装饰器中的 func 形参就是你想运行的函数,通过一个内部函数的方式在这个函数运行之前加一些代码,实际运行的是 wrapper 这个函数。
那如果有函数有返回值、有参数呢?
# 带有返回值的装饰器
def get_time_return(func):
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(f"has return decorator full time:{(end - start)}")
return res
return wrapper
@get_time_return
def get_sum2(num):
sum = 0
for i in range(num):
sum = sum + i
print(sum)
if __name__ == "__main__":
sum = get_sum2(100000)
print(sum)
如同第二段代码,只需在 wrapper 这个函数加入可变参数变量,在内部将 func 函数的返回值返回即可。
像之前所说,我们运行的实际是 wrapper 这个函数,由此会有一个问题:
if __name__ == "__main__":
sum = get_sum2
print(sum.__name__)
我们会看到输出结果是 wrapper,但我们可能不希望这个内置参数被改变(我们可能在使用 Log 时用到这个值)
def get_time_return(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(f"has return decorator full time:{(end - start)}")
return res
return wrapper
@get_time_return
def get_sum2(num):
sum = 0
for i in range(num):
sum = sum + i
print(sum)
if __name__ == "__main__":
sum = get_sum2
print(sum.__name__)
此时正确输出:get_sum2