1. 程式人生 > >Python之實戰裝飾器拆解

Python之實戰裝飾器拆解

實現裝飾器需要具備那些知識:

1.函式既”變數” 屬於可變化資料

函式是無關順序的,但是執行呼叫的函式必須在執行程式碼前面

示例:

變數:

a=[1,2]  #a為變數名,[1,2]存放記憶體裡面 ==專業稱之變數體

函式:

def test1():

   .....

#test1==該函式的名字(如變數名a)

#():內的程式碼 == [1,2]存放在記憶體裡面 ==專業稱之函式體

#注意1:test1獲取該函式的記憶體地址 、test1+ ()==執行該test1函式

#注意2:變數體(函式體)必須最少擁有一個變數名(函式名),否則記憶體回收

 

 

 

2.高階函式

a:把一個函式名當做實參傳給另外一個函式的函式:

通過實驗得到:在不修改被裝飾函式原始碼的情況下為其添加了功能

b:返回值中包含函式名

通過實驗得到:不修改函式的呼叫方式和原始碼也可以新增功能

示例:

import time

def bar():

    time.sleep(3)

    print('in the bar')



def test2(func):

    print(func)

    return func

test2(bar)()

#bar獲取的是函式bar函式的記憶體地址

#bar()才是執行該函式

3.巢狀函式

高階函式+巢狀函式=裝飾器

示例:

import time
def timmer(func):
    def warpper(*args,**kwargs):
        start_time = time.time()#開始時間
        func()#呼叫開始時間(該裝飾我還不清楚,目前這樣解釋)
        stop_time = time.time()#結束時間
        print('the func run time is %s' %(stop_time-start_time))#列印顯示xxx開始時間-
    return warpper
def test():
    time.sleep(3)#間隔3秒,也就是被呼叫了執行到該步驟的時候停3秒,繼續往下操作
    print('in the test')

a=timmer(test)  # a == warpper
a()             # a()==warpper()

#timmer(test)() == warpper()等於上面兩條命令

 

詳解:

  1. timmer(test1)得到的是warpper的該函式記憶體地址
  2. timmer(func)  func=test該函式體
  3. 賦值a  a() ==warpper()
  4. 全域性變數和區域性變數規則,意味著warpper()可以呼叫timmer函式的形參func
  5. 最終執行了func()  == test() 

 

timmer函式符合高階函式,和巢狀函式,所以是裝飾器

經過Python優化以後裝飾器呼叫變成如下:

@timmer裝飾到指定的函式如def test1()上面:

import time
def timmer(func):
    def warpper(*args,**kwargs):
        start_time = time.time()#開始時間
        func()#呼叫開始時間(該裝飾我還不清楚,目前這樣解釋)
        stop_time = time.time()#結束時間
        print('the func run time is %s' %(stop_time-start_time))#列印顯示xxx開始時間-
    return warpper


@timmer#呼叫裝飾器,在需要裝飾的函式的上方

def test():
    time.sleep(3)#間隔3秒,也就是被呼叫了執行到該步驟的時候停3秒,繼續往下操作
    print('in the test')

test()   

#帶裝飾器和正常寫法的轉換:

#func = test

#test = timmer(test)   ==  warpper

#test()=timmer(test)()  ==   warpper()

 

test該函式有形參怎麼辦?

1.我們知道func = test  

2.timmer(test1)得到的是warpper的該函式記憶體地址賦值到test

3.test() == warpper() 

4. warpper函式增加引數組(元祖和字典)

5. test(1,2) == warpper(1,2)     warpper函式執行func的時候在把形參給funcOKfun(1,2)

 

示例:

import time
def timmer(func):
    def warpper(*args,**kwargs):
        start_time = time.time()#開始時間
        func(args[0], args[1])#呼叫開始時間(該裝飾我還不清楚,目前這樣解釋)
        stop_time = time.time()#結束時間
        print('the func run time is %s' %(stop_time-start_time))#列印顯示xxx開始時間-
    return warpper


@timmer#呼叫裝飾器,在需要裝飾的函式的上方

def test(a,b):
    time.sleep(3)#間隔3秒,也就是被呼叫了執行到該步驟的時候停3秒,繼續往下操作
    print('in the test')

test(1,2)

#帶裝飾器和正常寫法的轉換:

#func = test

#test = timmer(test)   ==  warpper

#test1(1,2)=timmer(test)(1,2)  ==   warpper(1,2)

# func(args[0], args[1]) == test(1,2)

 

test該函式有return怎麼辦?

示例:

import time
def timmer(func):
    def warpper(*args,**kwargs):
        start_time = time.time()#開始時間
        res = func(args[0], args[1])#呼叫開始時間(該裝飾我還不清楚,目前這樣解釋)
        stop_time = time.time()#結束時間
        print('the func run time is %s' %(stop_time-start_time))#列印顯示xxx開始時間-
        return res
    return warpper

@timmer#呼叫裝飾器,在需要裝飾的函式的上方
def test(a,b):
    time.sleep(3)#間隔3秒,也就是被呼叫了執行到該步驟的時候停3秒,繼續往下操作
    return 1
res = test(1,2) 

高階裝飾器(其實都是一樣)