Python3.0之后加入新特性Decorators,以@為標記修飾function和class。有點類似c++的宏和java的注解。Decorators用以修飾約束function和class,分為帶參數和不帶參數,影響原有輸出,例如類靜態函數我們要表達的時候需要函數前面加上修飾@staticmethod或@classmethod,為什么這樣做呢?下面用簡單的例子來看一下,具體內容可以查看:官方解釋
不帶參數的單一使用
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)
運行結果
spam,spam,spam
10
函數useful本身應該只是打印10
,可是為什么最后的結果是這樣的呢,其實我們可以簡單的把這個代碼理解為
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)
不帶參數的多次使用
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)
運行結果
spam,spam,spam
spam1,spam1,spam1
10
這個代碼理解為
if __name__ == "__main__"
useful = spamrun1(spamrun(useful))
useful(a,b)
帶參數的單次使用
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)
運行結果
2.2
Guido van Rossum
2
這個代碼理解為
if __name__ == "__main__"
mymethod = attrs(versionadded="2.2",
author="Guido van Rossum).(mymethod)
mymethod(2)
帶參數的多次使用
這次我們來看一個比較實際的例子,檢查我們函數的輸入輸出是否符合我們的標準,比如我們希望的輸入是(int,(int,float))輸出是(int,float),這個例子在官網里有,但是在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)
這里故意輸入了錯誤的參數,所以運行結果將我們的斷言打印了出來
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做很多工作,簡化代碼,使邏輯更清晰等。還有更多的用法等著大家自己去挖掘了,這里只簡單的介紹了針對函數的用法,其實還可以針對class使用,具體的大家自己看看官方介紹,結合這篇文檔應該就不難理解了。