<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 431,  comments - 344,  trackbacks - 0

    原文地址:http://www.donews.net/limodou/archive/2004/12/19/207521.aspx

    在我以前介紹 Python 2.4 特性的Blog中已經介紹過了decorator了,不過,那時是照貓畫虎,現在再仔細描述一下它的使用。

    關于decorator的詳細介紹在 Python 2.4中的What's new中已經有介紹,大家可以看一下。

    如何調用decorator

    基本上調用decorator有兩種形式

    第一種:

    @A
    def f ():
        ...

    這種形式是decorator不帶參數的寫法。最終 Python 會處理為:

    f = A(f)

    還可以擴展成:

    @A
    @B
    @C
    def f ():
        ...

    最終 Python 會處理為:

    f = A(B(C(f)))

    注:文檔上寫的是@A @B @C的形式,但實際上是不行的,要寫成多行。而且執行順序是按函數調用順序來的,先最下面的C,然后是B,然后是A。因此,如果decorator有順序話,一定要注意:先要執行的放在最下面,最后執行的放在最上面。(應該不存在這種倒序的關系)

    第二種:

    @A(args)
    def f ():
        ...

    這種形式是decorator帶參數的寫法。那么 Python 會處理為:

    def f(): ...
    _deco = A(args)
    f = _deco(f)

    可以看出, Python 會先執行A(args)得到一個decorator函數,然后再按與第一種一樣的方式進行處理。

    decorator函數的定義

    每一個decorator都對應有相應的函數,它要對后面的函數進行處理,要么返回原來的函數對象,要么返回一個新的函數對象。請注意,decorator只用來處理函數和類方法。

    第一種:

    針對于第一種調用形式

    def A(func):
        #處理func
        #如func.attr='decorated'
        return func
    @A
    def f(args):pass

    上面是對func處理后,仍返回原函數對象。這個decorator函數的參數為要處理的函數。如果要返回一個新的函數,可以為:

    def A(func):
        def new_func(args):
            #做一些額外的工作
            return func(args) #調用原函數繼續進行處理
        return new_func
    @A
    def f(args):pass

    要注意 new_func的定義形式要與待處理的函數相同,因此還可以寫得通用一些,如:

    def A(func):
        def new_func(*args, **argkw):
            #做一些額外的工作
            return func(*args, **argkw) #調用原函數繼續進行處理
        return new_func
    @A
    def f(args):pass

    可以看出,在A中定義了新的函數,然后A返回這個新的函數。在新函數中,先處理一些事情,比如對參數進行檢查,或做一些其它的工作,然后再調原始的函數進行處理。這種模式可以看成,在調用函數前,通過使用decorator技術,可以在調用函數之前進行了一些處理。如果你想在調用函數之后進行一些處理,或者再進一步,在調用函數之后,根據函數的返回值進行一些處理可以寫成這樣:

    def A(func):
        def new_func(*args, **argkw):
            result = func(*args, **argkw) #調用原函數繼續進行處理
            if result:
                #做一些額外的工作
                return new_result
            else:
                return result
        return new_func
    @A
    def f(args):pass

    第二種:

    針對第二種調用形式

    在文檔上說,如果你的decorator在調用時使用了參數,那么你的decorator函數只會使用這些參數進行調用,因此你需要返回一個新的decorator函數,這樣就與第一種形式一致了。

    def A(arg):
        def _A(func):
            def new_func(args):
                #做一些額外的工作
                return func(args)
            return new_func
        return _A
    @A(arg)
    def f(args):pass

    可以看出A(arg)返回了一個新的 decorator _A。

    decorator的應用場景

    不過我也一直在想,到底decorator的魔力是什么?適合在哪些場合呢?是否我需要使用它呢?

    decorator的魔力就是它可以對所修飾的函數進行加工。那么這種加工是在不改變原來函數代碼的情況下進行的。有點象我知道那么一點點的AOP(面向方面編程)的想法。

    它適合的場合我能想到的列舉出下:

    1. 象文檔中所說,最初是為了使調用staticmethod和classmethod這樣的方法更方便
    2. 在某些函數執行前做一些工作,如web開發中,許多函數在調用前需要先檢查一下用戶是否已經登錄,然后才能調用
    3. 在某此函數執行后做一些工作,如調用完畢后,根據返回狀態寫日志
    4. 做參數檢查

    可能還有許多,你可以自由發揮想象

    那么我需要用它嗎?

    我想那要看你了。不過,我想在某些情況下,使用decorator可以增加程序的靈活性,減少耦合度。比如前面所說的用戶登錄檢查。的確可以寫一個通用的登錄檢查函數,然后在每個函數中進行調用。但這樣會造成函數不夠靈活,而且增加了與其它函數之間的結合程度。如果用戶登錄檢查功能有所修改,比如返回值的判斷發生了變化,有可能每個用到它的函數都要修改。而使用decorator不會造成這一問題。同時使用decorator的語法也使得代碼簡單,清晰(一但你熟悉它的語法的話)。當然你不使用它是可以的。不過,這種函數之間相互結合的方式,更符合搭積木的要求,它可以把函數功能進一步分解,使得功能足夠簡單和單一。然后再通過decorator的機制靈活的把相關的函數串成一個串,這么一想,還真是不錯。比如下面:

    @A
    @B
    def account(args):pass

    假設這是一個記帳處理函數,account只管記帳。但一個真正的記帳還有一些判斷和處理,比如:B檢查帳戶狀態,A記日志。這樣的效果其實是先檢查B、通過在A中的處理可以先執行account,然后再進行記日志的處理。象搭積木一樣很方便,改起來也容易。甚至可以把account也寫成decorator,而下面執行的函數是一個空函數。然后再通過配置文件等方法,將decorator的組合保存起來,就基本實現功能的組裝化。是不是非常理想。

    Python 帶給人的創造力真是無窮??!



    Trackback: http://tb.donews.net/TrackBack.aspx?PostId=207521

    posted on 2009-06-13 23:46 周銳 閱讀(1179) 評論(0)  編輯  收藏 所屬分類: Python
    主站蜘蛛池模板: 性色av极品无码专区亚洲| 国产免费一级高清淫曰本片| 青青青青青青久久久免费观看| 亚洲AV无码专区在线电影成人| 亚洲一级特黄大片无码毛片| 无码人妻一区二区三区免费看| 在线综合亚洲欧洲综合网站| 亚洲伊人成无码综合网 | 亚洲国产精品一区| 在线观看免费污视频| 中国好声音第二季免费播放| 亚洲一区精彩视频| 亚洲一区二区三区偷拍女厕 | 含羞草国产亚洲精品岁国产精品| 在线A亚洲老鸭窝天堂| 中文字幕人成无码免费视频| h在线看免费视频网站男男| 亚洲婷婷天堂在线综合| 国产成人亚洲综合无码| 成人在线免费观看| 久久免费区一区二区三波多野| 亚洲av无码专区在线观看下载 | 亚洲国产精品不卡在线电影| 全部免费毛片免费播放| 国产成人精品久久免费动漫 | 免费国产黄线在线观看| 免费无码黄网站在线看| 老司机亚洲精品影院在线观看| 亚洲欧洲国产精品你懂的| 亚洲国产成人精品无码久久久久久综合| 4399影视免费观看高清直播| 女人裸身j部免费视频无遮挡| 亚洲专区中文字幕| 久久精品亚洲日本佐佐木明希| 国产大片91精品免费看3| 青青草a免费线观a| 69视频在线是免费观看| 国产午夜不卡AV免费| 日本黄页网址在线看免费不卡| 亚洲色偷偷色噜噜狠狠99| 亚洲精品电影在线|