python語言特性之裝飾器
首先,python裝飾器的作用是:在不改變原有函式實現的前提下,給此函式增加一些額外的功能(在原有函式呼叫之前或者呼叫之後),好像給原有函式加上了一個裝飾的殼子。
通過一個例子解釋python裝飾器:
# -*- coding:utf8 -*- def w1(func): def inner(*args,**kwargs): print 'w1' func(*args,**kwargs) print func return inner def w2(func): print func def inner(*args,**kwargs): print 'w2' func(*args,**kwargs) return inner def w3(func): print func def inner(*args,**kwargs): print 'w3' func(*args,**kwargs) return inner @w3 @w2 @w1 def f1(arg1,arg2,arg3): print 'f1' f1(1,2,3)
以上是python多個裝飾器使用的例子,目的是為了更好說明裝飾器、以及裝飾器鏈的使用,裝飾器函式的呼叫順序等等。
那麼,在使用三個裝飾器裝飾f1函式,會怎麼執行呢,結果如何呢?
首先需要明確一個概念,函式和函式的呼叫。
以上程式碼中:f1、w1、w2、w3、inner等都是函式,函式其實在記憶體中就是一個地址。f1(1,2,3)是函式呼叫。很簡單的問題,很容易理解。
第二個概念:語法糖。(@函式名來裝飾函式名) 只舉一個例子:
@w1 def f1(arg1,arg2,arg3): print 'f1' 以上程式碼相當於 def f1(arg1,arg2,arg3): print 'f1' f1 = w1(f1)
注意:f1 = w1(f1) 中,作為引數的f1和返回的f1 已經不是同一個f1了。
好,先看看執行結果:
疑問1:w1 w2 w3三個裝飾器的執行順序是怎麼樣的?
疑問2:為什麼呼叫了三次裝飾器,只調用了一次f1,不應該每呼叫一次w就呼叫一次f1嗎?
第一個疑問:多個裝飾器的呼叫順序是自下往上,但是執行時的執行順序是自上往下!其實只需要記住呼叫順序是自下往上,執行順序可以從呼叫順序推出來!同理第二個疑問也可以通過相同辦法推出來。
根據以上語法糖的解釋,根據自下往上的呼叫順序,函式裝飾器還可以表示為以下方式:
def f1(arg1,arg2,arg3): print 'f1'
f1 = w1(f1) #1 把以上f1作為引數傳給w1,再把函式返回值傳回給f1(相當於給f1賦了新值,新的值為w1的返回值inner)
f1 = w2(f1) #2 把inner(注意,此時f1已經是w1的返回值inner)作為引數傳給w2,並且給f1重新賦新值
f1 = w3(f1) #3 把w2的返回值inner作為引數傳給f1,並且給f1重新賦值(w3的返回值inner)
為了更加清楚說明,我們翻譯如下:
f1 = w1(最初f1)
f1 = w2(w1函式返回值inner)
f1 = w3(w2函式返回值inner)
此時,我們呼叫函式f1(1,2,3),其實就是呼叫了w3裡面的inner函式。但是給w3傳的引數是w2的返回值inner。等呼叫到w3中func(*args,**kwargs)函式的時候,其實是呼叫了w2的內層函式inner。以此類推,直到呼叫w1內部的func(*args,**kwargs)函式的時候,才是呼叫的最初的f1函式,所以,其實f1函式只調用了一次,而且是按照w3、w2、w1、f1的順序執行。
以上就是python裝飾器的使用。