python裝飾器的參數傳遞

被裝飾器裝飾的函數名即便沒有被調用(由於有@xxx,會觸發運行裝飾器),(裝飾器工廠函數)定義裝飾器的代碼已經運行了(最內部的那個函數並無運行)(把被裝飾的原函數引用賦值給了裝飾器內部的那個函數名),當下邊經過該函數名調用時,會調用到裝飾器內部的那個函數()html

裝飾器:在不修改函數源代碼的基礎上,添加函數功能python

一個簡單的裝飾器app

def log_time(func):  # 此函數的做用時接受被修飾的函數的引用test,而後被內部函數使用
    def make_decorater():
        print('如今開始裝飾')
        func()
        print('如今結束裝飾')
    return make_decorater  # log_time()被調用後,運行此函數返回make_decorater()函數的引用make_decorater

@log_time  # 此行代碼等同於,test=log_time(test)=make_decorater
def test():
    print('我是被裝飾的函數')
test()  # test()=make_decorater()
D:\pycharm_project\裝飾器\venv\Scripts\python.exe D:/pycharm_project/裝飾器/venv/裝飾器.py
如今開始裝飾
我是被裝飾的函數
如今結束裝飾

Process finished with exit code 0

 當被裝飾的函數有形參時函數

def log_time(func):
    def make_decorater(*args,**kwargs):  # 接受調用語句的實參,在下面傳遞給被裝飾函數(原函數)
        print('如今開始裝飾')
        test_func = func(*args,**kwargs)  # 若是在這裏return,則下面的代碼沒法執行,因此引用並在下面返回
        print('如今結束裝飾')
        return test_func  # 由於被裝飾函數裏有return,因此須要給調用語句(test(2))一個返回,又由於test_func = func(*args,**kwargs)已經調用了被裝飾函數,這裏就不用帶()調用了,區別在於運行順序的不一樣。
    return make_decorater


@log_time
def test(num):
    print('我是被裝飾的函數')
    return num+1

a = test(2)  # test(2)=make_decorater(2)
print(a)
D:\pycharm_project\裝飾器\venv\Scripts\python.exe D:/pycharm_project/裝飾器/venv/裝飾器.py
如今開始裝飾
我是被裝飾的函數
如今結束裝飾
3

Process finished with exit code 0

 

當@裝飾器後有參數時code

def get_parameter(*args,**kwargs):  # 工廠函數,用來接受@get_parameter('index.html/')的'index.html/'
    def log_time(func):
        def make_decorater():
            print(args,kwargs)
            print('如今開始裝飾')
            func()
            print('如今結束裝飾')
        return make_decorater
    return log_time

@get_parameter('index.html/')
def test():
    print('我是被裝飾的函數')
    # return num+1

test()  # test()=make_decorater()
D:\pycharm_project\裝飾器\venv\Scripts\python.exe D:/pycharm_project/裝飾器/venv/裝飾器.py
('index.html/',) {}
如今開始裝飾
我是被裝飾的函數
如今結束裝飾

Process finished with exit code 0

 

 兩個裝飾器同時修飾一個函數(重點看執行順序)htm

def log_time1(func):
    def make_decorater(*args,**kwargs):  
        print('1如今開始裝飾')
        test_func = func(*args,**kwargs)  
        print('1如今結束裝飾')  
        return test_func  
    return make_decorater

def log_time2(func):
    def make_decorater(*args,**kwargs):  # 接受調用語句的實參,在下面傳遞給被裝飾函數(原函數)
        print('2如今開始裝飾')
        test_func = func(*args,**kwargs)  # 若是在這裏return,則下面的代碼沒法執行,因此引用並在下面返回
        print('2如今結束裝飾')
        return test_func  # 由於被裝飾函數裏有return,因此須要給調用語句(test(2))一個返回,又由於test_func = func(*args,**kwargs)已經調用了被裝飾函數,這裏就不用帶()調用了,區別在於運行順序的不一樣。
    return make_decorater

@log_time1
@log_time2
def test(num):
    print('我是被裝飾的函數')
    return num+1

a = test(2)  # test(2)=make_decorater(2)
print(a)
D:\pycharm_project\裝飾器\venv\Scripts\python.exe D:/pycharm_project/裝飾器/venv/裝飾器.py
1如今開始裝飾
2如今開始裝飾
我是被裝飾的函數
2如今結束裝飾
1如今結束裝飾
3

Process finished with exit code 0

 

注意看執行結果(print,只有執行就會輸出到屏幕)(return將數據返回給接受的變量或引用)blog

def makeBold(fn):
    def wrapped1():
        print('1')
        b = "<b>" + fn() + "</b>"  # 此行fn()調用了wrapped(),因此wrapped()執行了print輸出到屏幕,而後fn()接受到了wrapped() return返回的結果"<i>" + fn() + "</i>",因此須要等待wrapped()
print('1end') # 只有b = "<b>" + fn() + "</b>"執行完畢纔會執行這一行,只有wrapped()函數 return返回後,上一行代碼才執行
    return b return wrapped1 def makeItalic(fn): def wrapped(): print('2') a = return "<i>" + fn() + "</i>" # 此行fn()調用了test3(),因此test3()執行了,而後fn()接受到了test3()中returnd返回的結果"hello world-3",因此須要等待test3
print('2end') # 當test3()返回後,上一行代碼執行完畢,在屏幕上輸出此行
return a return wrapped @makeBold @makeItalic def test3(): return "hello world-3" # return 給了wrapped,wrapped又return給了wrapped; a = test3() # 此行test3() = wrapped1(),test3()調用了函數因此裝飾器才執行。a接受了裝飾器return的結果 print(a)
D:\pycharm_project\裝飾器\venv\Scripts\python.exe D:/pycharm_project/裝飾器/venv/text.py
1
22end1end
<b><i>hello world-3</i></b>

Process finished with exit code 0
相關文章
相關標籤/搜索