Python 裝飾器的理解

Python的裝飾器能夠實如今代碼運行期間修改函數的上下文, 便可以定義函數在執行以前進行何種操做和函數執行後進行何種操做, 而函數自己並無任何的改變。segmentfault

這個看起來很複雜, 實際上應用到了我以前說過的閉包的概念, 仔細看一看, 其實並不複雜。閉包

首先, 咱們先定義一個函數, 這個函數能夠輸出個人我的暱稱:app

def my_name():
        print "Yi_Zhi_Yu"
    my_name() # Yi_Zhi_Yu

那假如我須要在我的暱稱輸出前, 在輸出個人我的uid呢, 固然, 要求是不改動現有的my_name函數, 這個時候就可使用裝飾器了函數

首先, 裝飾器也是個函數, 其次, 他須要接受一個參數,該參數表示了要被裝飾的函數(即my_name):oop

def my_info(func):
        def wrapper(*args, **params):
            print 218
            return func(*args, **params)
        return wrapper

而後與相應的被裝飾函數關聯起來的方法就是使用@my_info寫在被裝飾函數的前面學習

@my_info
    def my_name():
        print "Yi_Zhi_Yu"

最後, 在執行my_name的時候, 就能既輸出個人uid, 又能輸出個人暱稱了ui

my_name()
    #218
    #Yi_Zhi_Yu

在上面, 最讓咱們疑惑的是裝飾器函數定義裏面的wrapper函數, 裝飾器自己返回的是wrapper函數的定義, 而wrapper中則定義了對被裝飾函數(my_name)的調用, func表示的就是被裝飾函數, 說白了, 裝飾器只是把某個不得改動的函數(a)放到另外一個函數(b)中, 在b裏面調用a, 在調用先後就能夠作所謂的看起來像裝飾的工做了。
my_info的最終返回的wrapper函數的定義, 並非執行結果,只有當wrapper真正執行的時候, 纔會真正的執行my_name方法, 這就是閉包時所說的內容。
wrapper中的參數, 實際上則是傳遞給func(其實是my_name)的參數code

由於裝飾器也是個函數, 那麼裝飾器本身的能不能有參數傳遞呢。能夠, 不過須要定義一個更高階的函數, 也就是外面還要套一層函數, 好比, 我還要輸出個人自定義的一個信息,須要傳遞參數get

def c_info(text):
        def my_info(func):
            def wrapper(*args, **params):
                print text
                print 218
                return func(*args, **params)
            return wrapper
        return my_info
        
     #使用裝飾器
     @c_info("Tony")
     def my_name():
        print "Yi_Zhi_Yu"
        
     my_name()
     #Tony
     #218
     #Yi_Zhi_Yu

與前面的那個裝飾器相比, 僅僅是多了個外層, 內層也僅僅是增長了對外層傳入參數(text)的調用學習筆記

總而言之, Python在函數定義中支持了對oop思想中的裝飾器的實現, 其本質也只是使用了閉包的思路, 延遲調用, 並在調用先後增長本身的其餘實現內容

Ps: 以上皆爲學習筆記, 附帶本身的理解, 不免有誤差, 若有發現紕漏, 還望指正

相關文章
相關標籤/搜索