1. 程式人生 > 其它 >Python裝飾器的妙用詳解 + python學習教程分享,及時收藏,不謝!

Python裝飾器的妙用詳解 + python學習教程分享,及時收藏,不謝!

1.開放封閉原則

簡單來說,就是 對擴充套件開放,對修改封閉

在面向物件的程式設計方式中,經常會定義各種函式。

一個函式的使用分為定義階段和使用階段,一個函式定義完成以後,可能會在很多位置被呼叫

這意味著如果函式的定義階段程式碼被修改,受到影響的地方就會有很多,此時很容易因為一個小地方的修改而影響整套系統的崩潰,

所以對於現代程式開發行業來說,一套系統一旦上線,系統的原始碼就一定不能夠再改動了。

然而一套系統上線以後,隨著使用者數量的不斷增加,一定會為一套系統擴充套件新增新的功能。

此時,又不能修改原有系統的原始碼,又要為原有系統開發增加新功能,這就是程式開發行業的開放封閉原則,這時就要用到裝飾器了。

2.什麼是裝飾器??

裝飾器,顧名思義,就是裝飾,修飾別的物件的一種工具。

所以裝飾器可以是任意可呼叫的物件,被裝飾的物件也可以是任意可呼叫物件

3.裝飾器的作用

在不修改被裝飾物件的原始碼以及呼叫方式的前提下為被裝飾物件新增新功能

原則:

目標:

4.裝飾器的定義和使用

來看下面的程式碼:

index函式的作用是程式在隨機睡眠1到5秒之後,列印一句話

現在想為index函式新增一個新功能:統計index函式的執行時間,該怎麼做呢??

修改index函式如下:

執行程式,執行結果如下:

可以看到,為index函式新增新功能確實實現了,但是卻違反了開放封閉原則。

在符合開放封閉原則的前提下,如果想為index函式新增新功能,此時就要使用裝飾器了

修改程式碼

執行程式,檢視執行結果

從程式執行結果可以看出,index函式的執行時間已經被統計出來了

但是檢視原始碼可以知道,index函式的原始碼確實沒有被修改,但是index的呼叫方式被修改了

而且還有一個問題就是,timmer這個裝飾器只能被用來裝飾index這個函式,如果以後想統計別的函式的執行時間,又要重新定義別的裝飾器,這樣也太不靈活了。

修改上面的程式碼

執行程式,檢視程式執行結果

可以看到,index函式的原始碼沒有被修改,index函式的呼叫方式也沒有改變,但是依然為index函式添加了統計時間的功能,這裡使用的就是裝飾器了。

來分析下上面程式碼的執行流程:

這就是裝飾器裝飾index函式的執行流程

5.裝飾器的簡化使用

現在我又有另外一個函式home,現在我也想統計home函式的執行時間,可以把程式碼修改如下

執行程式,執行結果如下

可以看到,每次呼叫統計程式執行時間的裝飾器timmer,都要先把被呼叫的函式的函式名作為引數傳給timmer裝飾器

然後再把timmer裝飾器的執行結果賦值給被呼叫的函式名本身,最後才能呼叫被裝飾的函式,太麻煩了有沒有??

其實python中的裝飾器可以簡化成下面的格式

程式執行結果

可以看出,使用 @加裝飾器名新增到被裝飾物件的上方的方式也可以為一個函式新增裝飾器中定義的功能

6.多個裝飾器的定義與呼叫

在上面的例子裡,定義並呼叫了一個統計程式執行時間的裝飾器timmer,

如果現在想為index函式新增一個使用者認證的功能,可以定義一個名為auth的裝飾器

執行程式

從程式執行結果可以看出,使用者登入密碼驗證的裝飾器auth已經定義並被成功呼叫了

如果想為index函式新增使用者認證的功能,又想統計index函式執行時間的功能,在使用裝飾器的情況下該怎麼呼叫呢

在上面的程式碼裡,為index函式添加了兩個裝飾器,現在有一個問題,就是這兩個裝飾器究竟哪個先被呼叫,哪個後被呼叫呢??

來分析一下,

執行程式,先輸入錯誤的使用者名稱和密碼以使用程式的執行時間加長

從程式的執行結果可以知道,程式是先執行timmer裝飾器,然後才執行auth裝飾器,所以timmer統計的時間就包括了使用者認證的時間,所以timmer統計到的程式執行時間遠遠大於index睡眠的2秒鐘

所以這裡得出一個結論:

把上面例子裡的timmer裝飾器和auth裝飾器位置互換一下

執行index函式,依然先輸入錯誤的使用者名稱和密碼,增加使用者認證的時間

可以看到,這次timmer統計到的時間只包含index函式的執行時間,不包含使用者進行認證的時間

來分析一下上面例子中,index函式被timmer裝飾器和auth裝飾器裝飾的程式碼裝飾流程

在上面得出結論,一個函式同時被兩個裝飾器時,加在下面的裝飾器先裝飾

至此,兩個裝飾器的裝飾過程已經知道了,來看程式的執行過程

所以這裡使用者輸入使用者名稱和密碼的時間不會被timmer裝飾器統計在內

7.被裝飾函式引數的設定與定義

先來看一段程式碼

如上所示,home函式添加了一個引數,而index函式並沒有引數

按照正常的函式的定義與呼叫方式,呼叫index函式和home函式的方式應該是下面這種形式

index()home("python")

然後我們執行程式就會發現,程式丟擲了異常

說個異常說明inner函式不需要位置引數,但是我們給了一個位置引數

回到timmer裝飾器定義的部分,可以看到,timmer裝飾器的內部函式確實沒有定義引數

這樣一來,timmer裝飾器只能用於裝飾沒有引數的函數了,

我們可以在timmer裝飾器定義的時候為inner函式新增一個引數

但是這樣一來,timmer裝飾器裝飾index函式的時候又會丟擲異常,因為index函式沒有引數

File "E:\python_learn\py_code\test.py", line 27, in index()
TypeError: inner() missing 1 required positional argument: 'name'

在不知道被裝飾函式的引數個數的情況下,即被裝飾函式的引數可變長,且形式不固定的時候,

最後,想學習Python的小夥伴們!

請關注+私信回覆:“學習”就可以拿到一份我為大家準備的Python學習資料!

pytyhon學習資料

python學習資料