1. 程式人生 > >兩個裝飾器的執行順序

兩個裝飾器的執行順序

兩個裝飾器的執行順序

如下,兩個裝飾器time_func 和auth_func分別實現了測試程式耗時和認證功能

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直譯器並不會執行裝飾功能,程式繼續向下執行

5.Python直譯器執行到@auth_func,因為裝飾的是一個函式test,定義test函式,申請一片記憶體地址,test指向它

6.裝飾器@auth_func 就相當於test = auth_func(test)

①執行等號左邊程式碼:test賦值給func2即func2指向了test的記憶體地址

②auth_func():執行函式auth_func,定義了函式inner2,申請1片記憶體地址,函式名inner2指向這片記憶體地址(此處並未呼叫函式,故看成1行程式碼),繼續向下執行,返回inner2

③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.先裝飾的後執行