函數的高級運用這部分知識的核心內容就是你要把「函數即變量」這個概念理解並運用得出神入化...
1、函數的遞歸調用
所謂遞歸調用就是函數本身調用本身,在Python中若是不作限制遞歸調用的死循環最多可循環調用999次,當超過999次的時候就會報錯。
函數遞歸調用的效率很低,咱們在寫代碼時不提倡使用,若是使用必定要有明確的結束條件。
def is_even():
num = int(input("Please input a number here: "))
if num % 2 == 0:
print("Good, the number is even number.")
return True
print("Your input is not Even number, please input again!")
is_even()
is_even()
2、高階函數
若是一個函數的入參是個函數名的話,那這個函數就是個高階函數。
def sum(x , y , z ):
res = z(x) + z(y)
return res
print(sum(1.98,3.14,int))
3、嵌套定義函數
函數的裏面是能夠再定義函數的,多層嵌套函數的做用域是採起就近並從內向外的原則,另外,函數只有被調用時才被執行。
def warpper():
print("我在外面")
def deco():
print("我在裏面")
def hhh():
print("xxx")
warpper()
函數的結果: 我在外面
由於在執行過程當中只有warpper()函數被調用了,至於它裏面的函數只是被定義了沒有被調用過。
name = 'python'
def warpper():
name = '函數第一層'
def deco():
name = '函數第二層'
print (name)
def hhh():
name = '函數第三層'
print(name)
hhh()
deco()
print(name)
warpper()hhh
函數結果:
函數第二層
函數第三層
函數第一層
由於首先調用warpper(): name 被賦值 ‘函數第一層’,以後定義函數deco只是定義不用管它,
接下來是調用deco(): name 被賦值爲‘函數第二層’,緊接着打印輸出這個name即函數第二層,以後定義hhh只是定義不用理它,
接下來是調用hhh(): name 被賦值爲‘函數第三層’,緊接着打印輸出這個name即函數第三層,到此deco()調用完畢,
接下來繼續執行warpper的最後一句,打印輸出 name,以前的name都是局域的變量執行完局部代碼就消失了,此處的neme仍然是最初
被賦值爲‘函數第一層’的name,因此剛剛被打印輸出。
3、裝飾器
裝飾器的定義其實就是函數嵌套加高階函數。它的用途是,給函數添加了功能,但調用函數時扔保持原樣不變,好像什麼四也米有發僧。
舉個栗子:
import time
def run(): # 定義一個簡單函數
print ("run ...")
time.sleep(3)
run() # 調用這個簡單函數
有需求,要查看這個函數執行的時間,因而程序變成下面的樣紙:
import time
def run():
print ("run ...")
time.sleep(3)
start_time = time.time() # 在函數調用以前獲取時間
run()
end_time = time.time() # 在函數執行結束是獲取時間
print("run()函數運行的時間是:", end_time - start_time)
繼續演化:
def run_time(func):
start_time = time.time()
func()
end_time = time.time()
print("run()函數的運行時間是:",end_time-start_time)
run_time(run)
繼續演化:其實這裏已經差很少是個裝飾器了
def timer(func):
def deco():
start_time = time.time()
func()
end_time = time.time()
print("runtime is: ", end_time-start_time)
return deco
run = timer(run)
run()
解釋以下:
def timer(func): # 定義一個對func進行處理的函數,func是個函數名,如何處理看裏面定義。
def deco(): # deco()便是把原func()豐富了計時功能後的那個函數 即變厲害了的func(),deco便是新func,咱們就是要用它來偷換原來的舊func。
start_time = time.time()
func()
end_time = time.time()
print("runtime is: ", end_time-start_time)
return deco # 對func進行處理後返回變厲害了新func名,deco。
run = timer(run) # 對run()處理後,把變厲害的run()的名字再交給run,這時候run已經不是原來的run,而是變厲害的run。
run() # 這裏不是run()在跑,而是厲害的新run()在跑,但看起來好像仍是原來的run()在跑。
上面這一整段代碼便是處理+置換的過程,而這個過程,把「函數即變量」運用得爐火純青... 裝飾器在定義的時候要更加適應被處理(或者叫作被裝飾)的函數參數的多樣化,這是第一點; 再有,實現偷天置換的關鍵語句run = timer(run),要讓這句看起來更具備假裝性。 基於以上倆緣由,標準的裝飾器寫法出爐了: import time def timer(func): # 定義裝飾器 def deco(*args,**kwargs): # 傳非必填形式參數,這樣即可應對被處理對象函數各類參數的狀況 start_time = time.time() func(*args,**kwargs) # 傳非必填形式參數,這樣即可應對被處理對象函數各類參數的狀況 end_time = time.time() print("runtime is: ", end_time-start_time) return deco @timer # 在定義被處理函數以前@裝飾器名字 def run(): print("run ...") time.sleep(3) run()過程能夠總結爲:定義裝飾器 ---> 在定義被處理的函數以前寫@裝飾器名字 ---> 最後在調用函數。先後順序不對的話,會報錯哦 ...