1. 程式人生 > >裝飾器之高階函數

裝飾器之高階函數

定義 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:綜上上述只能稱之為高階函數:並且使用了高階函數的第一個條件

裝飾器之高階函數