高階函數
a: 把一個函數名當作實參傳給另一個函數(在不修改被裝飾函數源代碼的狀況下爲其添加功能)
b: 返回值中包含函數名(不修改函數的調用方式)ide
# 如今寫一個裝飾器 # 兩個函數都有本身的邏輯,可以實現本身的功能 # 寫一個裝飾器,統計函數運行時間 1-1 import time def test1(): time.sleep(3) print('in the test1') def test2(): time.sleep(3) print('in the test2') # 統計test1 和 test2 的運行時間,可是前提是不能修改調用方式
1-1-1 # 如何不修改源代碼,給 test1 新增一個功能? import time def test1(): time.sleep(3) print('in the test1') def test2(): time.sleep(3) print('in the test2') # 寫一個高階函數 def deco(func): start_time = time.time() func() stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) # 那麼怎麼用? # 爲何 test1 不加括號,由於test1(),傳入的是返回值結果 deco(test1) deco(test2) ---> in the test1 the func run time is 3.0043373107910156 in the test2 the func run time is 3.0002830028533936
1-1-2 # 1-1-1 修改了函數的調用方式 # 如何不修改函數的調用方式? # 第二類高階函數,不改變函數的調用方式,在使用的時候就是 test1 = deco(test1) 這種方式 # 可是前提是 須要把函數修改爲 用 return 返回函數名的 第二種形式的高階函數 # 這樣,test1 就能夠獲取 deco 的返回值,deco 的返回值就是 test1 的 內存地址 # test1() 能夠正常調用,test2()也能夠 def deco(func): start_time = time.time() return func stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) import time def test1(): time.sleep(3) print('in the test1') def test2(): time.sleep(3) print('in the test2') test1 = deco(test1) test1() test2 = deco(test2) test2() ---> in the test1 in the test2 # 沒有修改函數的調用方式,也沒有新增功能,什麼都沒有作 # 爲何是這樣呢? # 由於 deco 中的 return,直接調用了 test1; # 以後的內容不會執行,這就是 return 的一個特性
1-1-3 # 由於 1-1-2 中一直在用高階函數,漏掉了嵌套 # 能夠引入嵌套函數 def deco(func): start_time = time.time() return func stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) def timer(): def deco(): pass # 這是嵌套函數,如何把這個函數,融入到上面的 deco中呢?
1-1-4 import time def timer(func): # timer(test1) 把 test1 的內存地址 傳給 func = test1 def deco(): start_time = time.time() func() stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) return deco # 返回 deco 函數的內存地址 # 這麼作之後,用到了高階函數,用到了函數嵌套 def test1(): time.sleep(3) print('in the test1') def test2(): time.sleep(3) print('in the test2') timer(test1) print(timer(test1)) # 返回 deco 的內存地址 ---> <function timer.<locals>.deco at 0x000002C818B1D558>
1-2 # 想要調用 timer(test1) 應該怎麼作? # 給它賦值,而後 test1 執行就能夠 import time def timer(func): # timer(test1) 把 test1 的內存地址 傳給 func = test1 def deco(): start_time = time.time() func() # run test1() stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) return deco # 返回 deco 函數的內存地址 # 這麼作之後,用到了高階函數,用到了函數嵌套 def test1(): time.sleep(3) print('in the test1') def test2(): time.sleep(3) print('in the test2') test1=timer(test1) test1() # 這時候,test1 執行,其實是在執行 deco 函數,由於 timer 返回的是 deco;deco作的事情是計算時間; func 的值是 test1 的值 ---> in the test1 the func run time is 3.000483751296997 # 成功加了一個新功能,沒有改變源代碼和調用方式; # 用到函數的嵌套,引用高階函數的定義,最終實現這樣的效果
1-3 # 可是 1-2 那樣 # test1=timer(test1) # test1() # 這種方式,有些麻煩;每次都須要運行裝飾器,運行一個和原來函數名同樣的東西 # 如何直接 test1() 運行呢? # 解釋器提供了一種語法,直接加 @timer;@ 後加上裝飾器的名字;寫在想要新增功能的函數的頭部 # @timer 就等同於 test1 = timer(test1) 這部操做 import time def timer(func): def deco(): start_time = time.time() func() stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) return deco @timer def test1(): time.sleep(3) print('in the test1') @timer def test2(): time.sleep(3) print('in the test2') test1() test2() ---> in the test1 the func run time is 3.000530958175659 in the test2 the func run time is 3.000612497329712 # 這兩個函數正常運行了,同時加上了新功能
1-1 # 若是 test2 裏面有一個參數 import time def timer(func): def deco(): start_time = time.time() func() stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) return deco @timer def test1(): time.sleep(3) print('in the test1') @timer def test2(name): print("test2:",name) test1() test2() ---> TypeError: test2() missing 1 required positional argument: 'name' # 結果是出錯的,test2 缺乏位置參數 name # @timer 至關於 test2 = timer(test2) # test2 傳到裏面都作了什麼? test2 → func → 執行 deco 因此,內嵌的deco函數,執行了嗎? # return deco,直接返回了 deco 的內存地址 # test2 實際上是等於 deco,因而 test2()至關於 deco(),執行到 func()時,至關於執行到了 test2() # 可是 test2 是要求傳參數的,test2()沒有傳參;因此會報錯 # 那麼,這種狀況應該如何處理?如何把參數傳進來?
1-2 # test2(name),其實就是至關於 deco(name) import time def timer(func): def deco(arg1): start_time = time.time() func(arg1) stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) return deco @timer def test2(name): print("test2:",name) test2("alex") ---> test2: alex the func run time is 0.0
1-2-1 # 若是傳入兩個參數呢? # 要裝飾的函數多是各類各樣的功能 # 因此須要 *args **kwargs import time def timer(func): def deco(*args,**kwargs): start_time = time.time() func(*args,**kwargs) stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) return deco @timer def test1(): time.sleep(3) print('in the test1') @timer def test2(name,age): print("test2:",name,age) test1() test2("alex",11) ---> in the test1 the func run time is 3.0008721351623535 test2: alex 11 the func run time is 0.0009975433349609375