Python中的注解“@”

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使用,具體的大家自己看看官方介紹,結合這篇文檔應該就不難理解了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,779評論 18 399
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,993評論 19 139
  • 前言 人生苦多,快來 Kotlin ,快速學習Kotlin! 什么是Kotlin? Kotlin 是種靜態類型編程...
    任半生囂狂閱讀 26,282評論 9 118
  • 說起人生,很多人對于這個虛幻而龐大的概念很是模糊,包括我,當然,每個人的人生軌跡都不一樣,自然而然對于人生...
    我是嘻哈大哥閱讀 779評論 0 0
  • 1 再長久的一生 不也就只是 就只是 回首時 那短短的一瞬 2 我可以鎖住我的筆 為什么 卻鎖不住愛和憂傷...
    A1dna閱讀 630評論 0 8