一、什麼是裝飾器
裝飾器本質上是一個Python函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的返回值也是一個函數對象。
二、怎麼在不改變函數的代碼下爲函數添加額外功能
在這個例子中,我們在不改動函數text代碼的情況下對函數進行添加額外功能,用了閉包的知識,把函數和添加的功能放在內部定義的函數,並且把該函數返回,並且賦值給一個叫innerfunc的變量,而如果此時把代碼修改一下,把innerfunc改成原來的函數名text,會是怎麼樣呢?
可以看出一樣的效果,爲什麼呢,其實當執行到最後第二行的時候,將原來建立的text變量由原來指向的函數空間改指向返回的inner函數內存空間。,而此時的text()執行了函數inner。
把text=w1(text)註釋掉,然後在text函數(被裝飾的函數)上面加上語法糖@+函數名(給予裝飾的函數)
可以看出,在text函數上加語法糖的效果和text=w1(text)是一樣的。這就是裝飾器的用法。
三、兩個裝飾器的情況
在上面說,@w1等價於text=w1(text),@w2等價於text=w2(text)
也從輸出的123看出是先執行inner1,inner2,再執行text
可是這裏的結果和想象的不一樣,其實它是這樣執行的,它雖然是先執行inner1函數,可是是對用下面的裝飾器進行裝飾,也就是先把text放到w2中進行裝飾,裝飾後此時變成<i>hello</i>,然後再放到w1中進行裝飾,纔得到結果,多個裝飾器也是這樣。
四、裝飾器執行時間
@w1等價於text=w1(text),這句語句其實右邊是對w1的調用,所以即使沒有對text進行調用,以及能輸出“裝飾”,證明在text函數執行前,其實text已經被裝飾了。
五、裝飾器對無參函數,有參函數進行裝飾
1.無參函數前面已經舉例了,下面主要對有參函數進行裝飾。
2.對有參函數進行裝飾
可以看出出現一個參數不匹配問題,就是第三行的函數沒有參數
所以使用這樣的函數,在func_in裏面加入倆個參數*args,**kwargs兩個就可以實現不定長參數函數的裝飾
六、對帶有返回值的函數進行裝飾
可以看出裝飾後並沒有返回值,在執行過程中,在@func裝飾後其實test指向了上面的func_in函數,func_in函數沒有返回值,所以返回None
而在這個程序中,第5行用xxx去保存返回的值,然後再返回xxx就可以實現返回了。
七、通用裝飾器(有無返回值,有無參數都能用)
在這個例子中可以看出無論是什麼函數都可以利用func進行裝飾,所以這個是通用裝飾器
八、帶有參數的裝飾器
可以看出裝飾器後面其實是可以加參數的,而這樣的裝飾器需要三層函數。