Python3.0之后加入新特性Decorators,以@為標記修飾function和class牺蹄。有點類似c++的宏和java的注解沃缘。Decorators用以修飾約束function和class,分為帶參數(shù)和不帶參數(shù)孵奶,影響原有輸出,例如類靜態(tài)函數(shù)我們要表達的時候需要函數(shù)前面加上修飾@staticmethod或@classmethod,為什么這樣做呢蜡峰?下面用簡單的例子來看一下了袁,具體內(nèi)容可以查看:官方解釋
不帶參數(shù)的單一使用
def spamrun(fn):
def sayspam(*args):
print("spam,spam,spam")
fn(*args)
return sayspam
@spamrun
def useful(a,b):
print(a*b)
if __name__ == "__main__"
useful(2,5)
運行結(jié)果
spam,spam,spam
10
函數(shù)useful本身應(yīng)該只是打印10
,可是為什么最后的結(jié)果是這樣的呢湿颅,其實我們可以簡單的把這個代碼理解為
def spamrun(fn):
def sayspam(*args):
print("spam,spam,spam")
fn(*args)
return sayspam
def useful(a,b):
print(a*b)
if __name__ == "__main__"
useful = spamrun(useful)
useful(a,b)
不帶參數(shù)的多次使用
def spamrun(fn):
def sayspam(*args):
print("spam,spam,spam")
fn(*args)
return sayspam
def spamrun1(fn):
def sayspam1(*args):
print("spam1,spam1,spam1")
fn(*args)
return sayspam1
@spamrun
@spamrun1
def useful(a,b):
print(a*b)
if __name__ == "__main__"
useful(2,5)
運行結(jié)果
spam,spam,spam
spam1,spam1,spam1
10
這個代碼理解為
if __name__ == "__main__"
useful = spamrun1(spamrun(useful))
useful(a,b)
帶參數(shù)的單次使用
def attrs(**kwds):
def decorate(f):
for k in kwds:
setattr(f, k, kwds[k])
return f
return decorate
@attrs(versionadded="2.2",
author="Guido van Rossum")
def mymethod(f):
print(getattr(mymethod,'versionadded',0))
print(getattr(mymethod,'author',0))
print(f)
if __name__ == "__main__"
mymethod(2)
運行結(jié)果
2.2
Guido van Rossum
2
這個代碼理解為
if __name__ == "__main__"
mymethod = attrs(versionadded="2.2",
author="Guido van Rossum).(mymethod)
mymethod(2)
帶參數(shù)的多次使用
這次我們來看一個比較實際的例子载绿,檢查我們函數(shù)的輸入輸出是否符合我們的標準,比如我們希望的輸入是(int油航,(int崭庸,float))輸出是(int,float),這個例子在官網(wǎng)里有冀自,但是在3.6版本中使用有些問題揉稚,這里進行了一些改動,如果要進一步了解可以看下functionTool熬粗。
def accepts(*types):
def check_accepts(f):
def new_f(*args, **kwds):
assert len(types) == (len(args) + len(kwds)), \
"args cnt %d does not match %d" % (len(args) + len(kwds), len(types))
for (a, t) in zip(args, types):
assert isinstance(a, t), \
"arg %r does not match %s" % (a, t)
return f(*args, **kwds)
update_wrapper(new_f, f)
return new_f
return check_accepts
def returns(rtype):
def check_returns(f):
def new_f(*args, **kwds):
result = f(*args, **kwds)
assert isinstance(result, rtype), \
"return value %r does not match %s" % (result, rtype)
return result
update_wrapper(new_f, f)
return new_f
return check_returns
@accepts(int, (int, float))
@returns((int, float))
def func(arg1, arg2):
return arg1 * arg2
if __name__ == "__main__"
a = func(1, 'b')
print(a)
這里故意輸入了錯誤的參數(shù)搀玖,所以運行結(jié)果將我們的斷言打印了出來
AssertionError: arg 'b' does not match (<class 'int'>, <class 'float'>)
這個代碼理解為
if __name__ == "__main__"
func = accepts(int, (int, float)).(accepts((int, float)).(mymethod))
a = func(1, 'b')
print(a)
說到這里,大家不難看出其實我們可以使用Decorators做很多工作驻呐,簡化代碼灌诅,使邏輯更清晰等。還有更多的用法等著大家自己去挖掘了含末,這里只簡單的介紹了針對函數(shù)的用法猜拾,其實還可以針對class使用,具體的大家自己看看官方介紹佣盒,結(jié)合這篇文檔應(yīng)該就不難理解了挎袜。