Python修飾器是什麼

Python 函數修飾

想在函數外面添加一些功能,單又不想改變原函數,那麼最方便的方法就是使用修飾器了。
我們先不討論python的修飾器是什麼?就先以一個test()函數開始。
那麼開始吧!
test()函數代碼:

def test(a, b):
    time.sleep(2)
    print("函數運行完畢")
    return a+b

test()函數有兩個參數a和b,函數裏面調用了個time.sleep(2)用來延時2s和一個print語句,最後返回一個a+b。
那打個比方說我是一個用戶,我想在調用完test()函數之後,知道test()函數執行需要多長時間。
那麼問題來了,既然是在調用test()函數之後知道test()函數運行多長時間,一下有幾種測試test()函數運行時間長度的方式:
方法1:

import time

def test(a, b):
    time.sleep(2)
    print("函數運行完畢")
    return a+b
		
start_time = time.time()
res = test(5, 3)
end_time = time.time()
print("res = %s" %res)
print("%s()函數運行時間爲%s" %(test.__name__, end_time-start_time))

start_time = time.time()
res = test(6, 5)
end_time = time.time()
print("res = %s" %res)
print("%s()函數運行時間爲%s" %(test.__name__, end_time-start_time))

運行結果:

函數運行完畢
res = 8
test()函數運行時間爲2.002138137817383
res = 11
test()函數運行時間爲2.002138376235962

程序在第8行使用了一個時間戳start_time變量用來記錄程序運行的開始時間,然後在時間戳後面運行用戶自定義函數,然後在用一個end_time變量來記錄用戶函數運行完畢之後的時間戳,最後通過起始時間和截止時間之基差來獲取用戶輸入時間長度。其實後面的計算函數運行時間基本都是使用這種計時方式。如果說每次調用test()函數的時候都那麼寫是不是有些臃腫了,當然有簡便的方法了,那就跟函數封裝相識了,這個後面會說。

方法2:

#!/usr/bin/python3
print("hello world !!!")

import time

def Embellish(fun):
    def Embellish_demo(*args, **kwargs):	#使用可邊長參數
        start_time = time.time()
        res = fun(*args, **kwargs)		#使用可編程參數
        end_time = time.time()
        print("%s()函數運行時間爲%s" %(fun.__name__, end_time-start_time))
        return res
    return Embellish_demo

@Embellish
def test(a, b):
    time.sleep(2)
    print("函數運行完畢")
    return a+b

res = test(5, 3)
print("res = %s" %res)

res = test(6, 5)
print("res = %s" %res)

運行結果:

hello world !!!
函數運行完畢
test()函數運行時間爲2.002136468887329
res = 8
函數運行完畢
test()函數運行時間爲2.0021605491638184
res = 11

終於輪到解釋修飾器了,求實修飾器也就是個外包裝,就像你現在有一個產品需要包裝一下加個殼子貼上封面類似,實質上不會改變函數內部核心代碼。
代碼解釋:Embellish()line6函數就是個修飾函數,爲什麼那麼說那?
仔細看,在Embellish()line6函數的參數是一個裏面定義了一個Embellish_demo()line7函數,先看Embellis_demo()line7函數然後在看Embellish()line6函數的參數,從Embellish_demo()line7函數裏面可以看出line8-line10行與前面講的相似,只不過是吧test()換成了fun()line9,現在再來看看Embellish()line6函數的參數funline6在這裏竟然可以寫成一個函數的形式,那麼Embellish()line6函數的參數就是一個函數名。好了既然函數名傳進來了那麼在看看fun()line9函數的參數是從哪裏傳進來的,看着fun()line9函數的參數與Embellish_demo()line7函數的參數一樣,沒錯fun()line9函數的參數就是從Embellish_demo()line7函數的參數傳進來的。而fun()line9函數的返回值是通過Embellish_demo()line12函數的返回值進行返回的。再看Embellish()line13函數的最後一行他竟然返回的是Embellish_dem()line7函數的函數名,既然是函數名那麼函數名加上一個括號就能執行了。
哎!說了那麼多也只是一個修飾函數,其實真正用的是一個修飾器,修飾器就是讓你的修飾函數和被修飾函數組合起來,@Embellishline15就是調用了修飾器@,作用就是在你每次調用test()line21函數的時候直接調用了Embellish_demo()line7函數,省去了那麼臃腫的代碼是不是很簡便。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章