Python装饰器是什么
Python装饰器就是一个函数,它的产生是为了在不改变目标函数结构的基础上为其增加功能,返回值是增加功能后的目标函数。
一个简单的装饰器 -为程序添加简单的计时功能
import time
def get_run_time(method):
def wrapper():
start = time.time()
method()
end = time.time()
return end - start
return wrapper
@get_run_time
def helloworld():
print('helloworld')
if __name__ == '__main__':
spend = helloworld()
print('spend time: {}'.format(spend))
运行结果:
...
helloworld
spend time: 1.50203704834e-05
目标函数带参数的情况
当然有时候目标函数(在上面的程序中为helloworld
函数)是有参数的,下面做一些微小的改动
import time
def get_run_time(method):
def wrapper(*args, **kwargs):
start = time.time()
method(*args, **kwargs)
end = time.time()
return end - start
return wrapper
@get_run_time
def helloworld(name):
print('I\'m {}, helloworld'.format(name))
if __name__ == '__main__':
spend = helloworld('wk')
print('spend time: {}'.format(spend))
运行结果:
...
I'm wk, helloworld
spend time: 2.09808349609e-05
装饰器函数带参数的情况
既然装饰器是个函数,那它也是可以有参数的,此时只要将上述代码稍加改动即可
import time
def get_run_time(decimal):
def wrapper_of_wrapper(method):
def wrapper(*args, **kwargs):
start = time.time()
method(*args, **kwargs)
end = time.time()
return round(end - start, decimal)
return wrapper
return wrapper_of_wrapper
@get_run_time(decimal=16)
def helloworld(name):
print('I\'m {}, helloworld'.format(name))
if __name__ == '__main__':
spend = helloworld('wk')
print('spend time: {}'.format(spend))
# 下面这行先不用看,这是下一个标题的内容
print(helloworld.__name__)
增加了控制返回时间精度的功能,其实就是在原基础上多封了一层,最外层是新增的一层,目的是增加一个相对全局变量(能看懂就行了,能力有限,就不扯深的了),在上述代码中是decimal
执行结果:
...
I'm wk, helloworld
spend time: 4.60147857666e-05
wrapper
@functools.wraps
装饰器返回的函数虽然结构与目标函数相似,但本质已经发生了变话,返回的是另一个函数,看上面程序中print(helloworld.__name__)
的输出为wrapper
,再看看functools.wraps的效果
import time
import functools
def get_run_time(decimal):
def wrapper_of_wrapper(method):
@functools.wraps(method)
def wrapper(*args, **kwargs):
start = time.time()
method(*args, **kwargs)
end = time.time()
return round(end - start, decimal)
return wrapper
return wrapper_of_wrapper
@get_run_time(decimal=16)
def helloworld(name):
print('I\'m {}, helloworld'.format(name))
if __name__ == '__main__':
spend = helloworld('wk')
print('spend time: {}'.format(spend))
# 对比一下,只增加了@functools.wraps
print(helloworld.__name__)
运行结果:
...
I'm wk, helloworld
spend time: 2.09808349609e-05
helloworld