很久以前就有看过装饰器的用法和功能,但是自己平时在编程的时候基本上很少用到这些高级的用法。今天看别人开源的efficientDet的源码时,很多地方用了装饰器,一时想不起来具体作用了,所以又百度学习了一波。现在以我个人理解总结下,以便日后忘记可以在复习下。
首先装饰器是python一个很强大的功能,也是动态编程的一个特点。
首先我们知道,在python中一个函数可以作为参数传给另外一个函数:
def hi():
return "hi yasoob!"
def doSomethingBeforeHi(func):
print("I am doing some boring work before executing hi()")
print(func())
doSomethingBeforeHi(hi)
#outputs:I am doing some boring work before executing hi()
# hi yasoob!
下面装饰器的用法,就是“装饰一个函数”让这个被装饰的函数作为装饰器的参数进行调用:
import functools
def itcast1(fun):
# 带参数的装饰器
def inner(*args, **kwargs):
print("itcast1 start")
fun(*args, **kwargs)
print("itcast1 end")
return inner
@itcast1
def say_hello():
print('say_hello')
print(say_hello.__name__)
say_hello
>> output: inner
itcast1 start
say_hello
itcast1 end
可以看到,被装饰之后的函数,就不是函数本身了,名字变成了装饰器的返回函数,并且是直接调用inner函数,所以输出调用的顺序就如inner里面的顺序。这样做可以大大简化我们的代码,将装饰器的功能写好,直接装饰给其他函数就可以了。
接下来看看warp,它作用主要是保持原有函数的名字,doc的属性。
import functools
def itcast1(fun):
@functools.wraps(fun)
def inner(*args, **kwargs):
print('itcast1 start')
a=fun(*args, **kwargs)
print("itcast1 end")
return inner
@itcast1
def say_hello(a):
print('say_hello')
print(a)
return a
print(say_hello.__name__)
say_hello()
>>output:
say_hello
itcast1 start
say_hello
itcast1 end
从输出可以看出,函数的名字没变还是原有函数,而同时继承了装饰器内的功能。
如果我们被装饰的函数有返回值,我们想得到这个返回值,只需要在inner里返回就可以了。如下:
import functools
def itcast1(fun):
@functools.wraps(fun)
def inner(*args, **kwargs):
print('itcast1 start')
a=fun(*args, **kwargs)
print("itcast1 end")
return a
return inner
@itcast1
def say_hello(a):
print('say_hello')
print(a)
return a
print(say_hello.__name__)
a=say_hello(1)
print(a)
>>output:
say_hello
itcast1 start
say_hello
1
itcast1 end
1
详细看这个:https://www.liaoxuefeng.com/wiki/897692888725344/923030547069856