看了不少python關于裝飾器文章,覺得還挺實用,發貼來mark一下(以前做筆記總會長時間不看就忘記,放這里應該不會忘了吧 - -)
先來看一個簡單的知識點:
def a():print("I'm a")#a 代表這個函數,在Python中函數名只是個指向函數首地址的函數指針而已 a() #執行函數
ok,接下來開始講裝飾器,看下面的小例子:
def a(func):print("a running!")return func@a def b():print("b running!")b()
當python讀到@a的時候,其實執行的相當于 b=a(b),將下面的函數作為參數帶入執行。這樣我們在帶入讀下是不是變得很簡單了,就是將b作為參數帶入函數a中執行,再把函數a返回的結果賦值給b,等于重新定義了函數b;再來看內部的執行過程:
直接從@a開始,@a <==> b=a(b) ?
1.執行參數為b的a函數,打印“a running”
2.返回b,并將b賦值給b(這樣也等于啥也沒變!)所以也沒有什么卵用!接下來我們再看一個開發中常用到的示例
示例2:
def a(b):print("a running!")def c():print("c running!")return b()return c@a def b():print("b running!")b()
再看看這個函數的執行過程:
1.先將@a <==> b=a(b) ,相當于函數b等于被重新定義為a(b)的返回結果,
2.跳轉a(b)的執行過程,先打印a running! 說明a運行了,接下來定義一個函數c,沒啥輸出,因為還沒調用這個函數!注意這里的c函數return的b()的不是一個函數了啊,而是這個函數執行的結果,是將這個函數的結果作為返回值!這么做是有原因的(請看最后)
3.接下來才是return一個函數c,是不是相當于b=c(這就很有用了,在不改變函數b的情況下拓展了b的功能,真爽啊!)
所以最后這個b被定義成了這樣:
b=def c():print("c runing!")return b()
4.再來執行b(),看看是不是輸出了 c running !,又運行b()作為返回結果給調用者,當然函數b沒有定義返回內容額,所以只運行了b()
?
最后解釋下為什么要用return b(),return b()是運行b(),然后將返回的結果再返回,
這樣想想看,沒有使用裝飾器之前,我調用b()是不是就是返回b()的結果啊,
現在加上裝飾器,返回的是不是依然是b()的結果,這樣對外看來我們調用b好像完全沒有改變,但是實際上b在運行之前已經運行了我們的拓展功能了。。。不得不說666啊
總的來看其實主要就是@a 等價于 b=a(b) 理解了這個就ok啦,好處就是在不影響b函數的情況下,因為執行b還是返回原來的b返回的內容,增加了b函數的功能,是不是挺方便!!
?