兩個裝飾器的執行順序
以下,兩個裝飾器time_func 和auth_func分別實現了測試程序耗時和認證功能python
import time user_name = "zb" user_pwd = "123" def time_func(func1): print("time") def inner1(): print("from inner1") start_time = time.time() func1() stop_time = time.time() print(stop_time-start_time) return inner1 def auth_func(func2): print("auth") def inner2(): print("from inner2") name = input("input your name:").strip() pwd = input("input your password:").strip() if name == user_name and pwd == user_pwd: print("login successful") func2() else: print("name or password error") return inner2 @time_func @auth_func def test(): print("from test") test()
1.python解釋器從上而下執行代碼:導入時間模塊,定義變量用戶名和密碼閉包
2.遇到裝飾器(閉包函數)time_func,申請了1片內存地址,函數名time_func指向了這片內存地址,程序繼續向下執行(這裏只是定義了函數,並不會執行,因此至關於1行代碼)函數
3.遇到裝飾器auth_func,這裏同第2步,申請1片內存地址,函數名auth_func 指向這片內存地址,程序繼續向下執行測試
4.解釋器執行到裝飾@time_func這裏,此行代碼下是一個裝飾器@auth_func而不是一個函數,python解釋器並不會執行裝飾功能,程序繼續向下執行spa
5.Python解釋器執行到@auth_func,由於裝飾的是一個函數test,定義test函數,申請一片內存地址,test指向它 3d
6.裝飾器@auth_func 就至關於test = auth_func(test)code
①執行等號左邊代碼:test賦值給func2即func2指向了test的內存地址blog
②auth_func():執行函數auth_func,定義了函數inner2,申請1片內存地址,函數名inner2指向這片內存地址(此處並未調用函數,故當作1行代碼),繼續向下執行,返回inner2ip
③test接收返回值inner2即test指向了inner2的內存地址 內存
7.裝飾器@time_func執行,test = time_func(test),
①test賦值給func1即func1指向test的內存地址(此時test指向了inner2),故func1指向了inner2,
②定義了函數inner1,申請1片內存地址,函數名inner1指向這片內存地址(未調用函數,故當作1行代碼),繼續向下執行,返回inner1
③test接收返回值inner1,test指向了inner1的內存地址
8.調用函數test(),執行test指向的內存地址代碼即inner1,inner1中的func1指向了inner2,inner2中的func2指向了test
inner1()
inner2()
test()
運行結果 inner1,inner2
實際運行結果以下,先裝飾了auth_func,後裝飾了time_func,先執行了計時功能,後執行了驗證功能(此處特意延緩輸入的時間,若是是先執行的驗證功能,此處耗時應該很短)
倒個順序裝飾:耗時0.0s極快
總結:1.靠近函數的先裝飾
2.先裝飾的後執行