裝飾器之高階函數
阿新 • • 發佈:2019-01-24
定義 lib 運行時 本質 添加 一段 span 實現 div
高階函數概念引入:滿足下面兩個條件之一便可以稱為高階函數
1:把一個函數的函數名當作實參傳給另外一個函數。
2:返回值中包含函數名。
下面是一段簡單的高階函數的代碼使用條件1:
# Author:Ju BO ‘‘‘ def bar(): print("in the bar") def test1(func): print(func) #----相當於打印bar這個函數在內存中的門牌號即內存地址 func()#----相當於bar(),調用bar這個函數 test1(bar)#----將bar函數名當作實參傳給test1函數,test1函數用形參func來接收它。 ‘‘‘
下面是一段在第一段代碼的基礎上新增了一些功能的高階函數,從中也慢慢顯示出了裝飾器的影子。
#----改進------------------ #這段代碼的功能為統計bar這個函數的運行時間 import time #---導入庫 def bar(): time.sleep(3) #---等3秒 print("in the bar") def test1(func): start_time = time.time() #----截取開始時間 func() #---相當於bar(),運行bar這個函數 stop_time = time.time() #-----截取結束時間 print("the func run time is %s"%(stop_time - start_time))#---結束時間-開始時間 = bar的運行時間 test1(bar) #--將bar當作實參傳遞給test1
3:觀察第二段代碼發現貌似已經實現了裝飾函數的功能,之前沒有test1這個函數時,bar這個函數單純的功能為打印“in the bar”,而現在test1這個函數附加了一個功能:計算bar這個函數的運行時間。那麽根據裝飾器的定義:本質是函數,目的是為其他函數添加附加功能,test1這個函數可以稱之為裝飾器嗎?其實不然,暫時還不能稱它為裝飾器。因為要稱之為裝飾器,必須還要遵循2 個原則:
(1):不能修改被裝飾函數的源代碼。
(2):不能修改被裝飾的函數的調用方式。
4:為什麽不能稱test1為裝飾器呢?原因很簡單,依據3中提出的兩個原則:首先明確bar是要被裝飾的函數,test1該函數並沒有修改它的源代碼,滿足第一條。但是顯然第二條原則不滿足,之前我們調用bar這個函數時是這樣調用的:bar(),但是現在變成這樣了:test1(bar),然後再在test1函數中調用bar,改變了bar這個函數的調用方式
5:綜上上述只能稱之為高階函數:並且使用了高階函數的第一個條件。
裝飾器之高階函數