装饰器的作用是在不改变现有函数的结构上添加新的功能
比如现在有个函数A
import time
def A():
for i in range(3):
time.sleep(0.2)
print(i, end=" ")
A()
>> 0 1 2
现在我们想要在不改变函数A的前提下想要知道程序运行一次需要多久的时间,使用装饰器
import time
import functools
def detection_runtime(func):
@functools.wraps(func)
def detection(*args,**kwargs): # 原函数也就是func接收的参数会被传递到这里
start = time.clock()
result = func(*args,**kwargs)
end = time.clock()
print("runtime is {}".format(end-start))
return result
return detection
上面的装饰器已经写好,下面调用装饰器,有两种方式
方式一:使用@方式
import time
import functools
def detection_runtime(func):
@functools.wraps(func)
def detection(*args,**kwargs):
start = time.clock()
result = func(*args,**kwargs)
end = time.clock()
print("runtime is {}".format(end-start))
return result
return detection
@detection_runtime
def A():
for i in range(3):
time.sleep(0.2)
print(i, end=" ")
A()
>> 0 1 2 runtime is 0.5995562511980463
方式二:像函数一样调用
import time
import functools
def detection_runtime(func):
@functools.wraps(func)
def detection(*args,**kwargs):
start = time.clock()
result = func(*args,**kwargs)
end = time.clock()
print("runtime is {}".format(end-start))
return result
return detection
def A():
for i in range(3):
time.sleep(0.2)
print(i, end=" ")
A = detection_runtime(A) # 这种方式在你无法修改源代码的时候比较适合使用
A()
>> 0 1 2 runtime is 0.5998113312916864
魔法方法__name__可以打印函数的名字
多个装饰器共同装饰一个函数的情况
当有多个装饰器装饰同一个函数的时候,离函数近的装饰器优先执行
from functools import wraps
def decoratort1(func):
@wraps(func)
def decorator(*args,**kwargs):
return "<b>" + func(*args,**kwargs) + "</b>"
return decorator
def decoratort2(func):
@wraps(func)
def decorator(*args,**kwargs):
return "<i>" + func(*args,**kwargs) + "</i>"
return decorator
@decoratort1
@decoratort2
def test(): # decoratort2 会优先装饰
return "hello world"
print(test())
>> <b><i>hello world</i></b>
三层装饰器
如果装饰器需要传参就需要三层装饰器了,框架的路由其实就是使用的三层装饰器
from functools import wraps
def decoratort_outer(arg1=None):
print("received arg : {}".format(arg1))
def decoratort_middle(func):
@wraps(func)
def decorator(*args,**kwargs):
return "<b>" + func(*args,**kwargs) + "</b>"
return decorator
return decoratort_middle
@decoratort_outer("hello python")
def test():
return "hello world"
print(test())
>> received arg : hello python
>> <b>hello world</b>
同时支持两层和三层的通用装饰器
from functools import wraps
def decoratort_outer(func):
if callable(func):
@wraps(func)
def decorator(*args, **kwargs):
return "<b>" + func(*args, **kwargs) + "</b>"
return decorator
else:
print("received arg : {}".format(func)) # 注意这个func是装饰器传递的参数
def decoratort_middle(func): # 这个func是被装饰的函数
@wraps(func)
def decorator(*args,**kwargs):
return "<b>" + func(*args,**kwargs) + "</b>"
return decorator
return decoratort_middle
@decoratort_outer("hello python")
def test():
return "hello world"
@decoratort_outer
def test1():
return "haha"
print(test())
>> received arg : hello python
>> <b>hello world</b>
print(test1())
>> <b>haha</b>
网友评论