接上一篇继续说装饰器的具体应用:
首先看例子:
impor time
def get_time(func):
def inner():
agin=time.time()
func()
agin2=time.time()
print('运行函数一共耗时%f'%(agin2-agin))
return inner
@get_time
def time1():
time.sleep(2)
print('in func 1')
if __name__ == '__main__':
time1()
运行结果:
in func 1
运行函数一共耗时2.012976
这个函数在不改变原函数的情况下,计算出了函数运行的时间,这就是装饰器最基本的应用
那装饰器只能装饰一个函数吗? 当然不是
在看例子:
impor time
def get_time(func):
def inner():
agin=time.time()
func()
agin2=time.time()
print('运行函数一共耗时%f'%(agin2-agin))
return inner
@get_time
def time1():
time.sleep(1)
print('in func 1')
@get_time
def time2():
time.sleep(2)
print('in func 2')
运行结果:
in func 1
运行函数一共耗时1.004989
in func 2
运行函数一共耗时2.000298
那如果我们需要在函数中添加参数怎么办? 该如何解决
在看下面的例子:
import time
def get_time(func):
def inner(*args,**kwargs):
agin=time.time()
func(*args,**kwargs)
agin2=time.time()
print('运行函数一共耗时%f'%(agin2-agin))
return inner
@get_time
def time1(num1):
time.sleep(1)
print('in func %s'%num1)
@get_time
def time2(num2, num3):
time.sleep(2)
print('in func %s'%(num2 + num3))
if __name__ == '__main__':
time1(2)
time2(1,2)
运行结果:
in func 2
运行函数一共耗时1.010108
in func 3
运行函数一共耗时2.000327
因为每个装饰器能给所有的函数使用,为了确保传入的参数是合理的我们使用args与kwargs,这种装饰器也是通用装饰器
接下来看一个装饰器的注意点(被装饰函数有返回值):
import time
def get_time(func):
def inner(*args,**kwargs):
agin=time.time()
func(*args,**kwargs)
agin2=time.time()
print('运行函数一共耗时%f'%(agin2-agin))
return inner
@get_time
def time1(num1):
time.sleep(1)
print('in func %s'%num1)
return 1000
if __name__ == '__main__':
ret = time1(2)
print('接收到的返回值是%s'%ret)
运行结果:
in func 2
运行函数一共耗时1.005030
接收到的返回值是None
此时接收到的ret是None那为什么没有接收到呢? 是因为咱们调用time1函数时其实是调用的inner函数所以并没有接收到
import time
def get_time(func):
def inner(*args,**kwargs):
agin=time.time()
ret = func(*args,**kwargs)
agin2=time.time()
print('运行函数一共耗时%f'%(agin2-agin))
return ret
return inner
@get_time
def time1(num1):
time.sleep(1)
print('in func %s'%num1)
return 1000
if __name__ == '__main__':
ret = time1(2)
print('接收到的返回值是%s'%ret)
此时的结果为:
in func 2
运行函数一共耗时1.009920
接收到的返回值是1000
咱们只需要在inner函数中接收time1返回的值并输出就可以成功接收到了
多个装饰器的使用
@外套
@长袖
def 没有穿衣服的你():
pass
当有两个装饰器的时候,就比如你穿衣服你会先穿长袖,然后再穿外套,装饰器也是这样谁先来的就先装饰,然后在装饰外面的装饰器
举例:
def makeDiv(func):
def inner():
return "<div>" + func() + "<div>"
return inner
def makeP(func):
def inner():
return "<p>" + func() + "<p>"
return inner
@makeP
@makeDiv
def aaa():
return '被装饰函数'
if __name__ == '__main__':
print(aaa())
运行结果:
<p><div>被装饰函数<div><p>
两个装饰器装饰可以用一句代码理解:aaa=makeP(makeDiv(aaa))
那如果装饰器带有参数该如何传入函数中呢? 我们可以采用闭包把参数传入
例子:
import time
def get_num(num):
def get_time(func):
def inner(*args,**kwargs):
agin=time.time()
func(*args,**kwargs)
agin2=time.time()
if num == 1:
print('运行函数一共耗时%f'%(agin2-agin))
else:
print('运行函数一共耗时%d'%int(agin2-agin))
return inner
return get_time
@get_num(1)
def time1(num1):
time.sleep(2)
if __name__ == '__main__':
time1(2)
装饰器带有参数的情况下,我们可以采用闭包的形式传给函数,因为内部函数可以使用外部函数的参数(上篇讲过)