決戰Python之巔(十一)

2021-09-02 23:46:20 字數 2418 閱讀 3963

本篇將介紹遞迴以及函式的內建方法。

之前我們已經講過,函式內部可以呼叫其他函式。如果乙個函式在內部呼叫自身,這個函式就是遞迴函式:

def func()

print('遞迴函式')

func()

這就是乙個遞迴函式,如果你執行這段**的話,理想中會列印無數行 遞迴函式。但事實上並不會… 因為目前這個遞迴相當於乙個死迴圈,一直執行下去很快會將記憶體撐爆,而python為了防止這種情況發生就給遞迴次數做了乙個限制,大概是1000次(這是預設次數,有需要你也可以自己手動修改。)

…其實到這裡遞迴就已經講完了- -

為了顯得專業一點,高階一點,實質上限制遞迴次數的原因是:在計算機中,函式呼叫是通過『棧』這種資料結構實現的,每呼叫一次函式,棧就會加一層棧幀來儲存這層函式的資料;函式每return一次,棧中就減少一層。因為棧的大小是有限的,如果函式呼叫次數太多就會導致棧溢位。

這裡我們實現乙個需求,階乘。階乘我們都學過,數學公式是: n! = n*(n-1)*(n-2)…*3*2*1

也就是:n! = n * (n-1)!,那麼用遞迴怎麼實現呢?

def  func(n):

#判斷n是否為1,是則直接返回1

if n == 1:

return 1

# n的階乘都等於n乘以(n-1)的階乘

return n * func(n-1)

假設n>1,第一次呼叫,進入第一層,先判斷n是否等於1,等於直接返回1(1的階乘就是1),不等於返回n*f(n-1),這時候第二次呼叫函式,進入第二層,先判斷n-1是否等於1,是就直接返回1,此時f(n-1)=1,且第二層結束,回到第一層,計算n*f(n-1),然後第一層結束;n-1不等於1,就返回 (n-1)*f(n-2),此時第三次呼叫這個函式,進入第三層,注意前面兩層還沒有結束,第二層在等第三層的f(n-2),第一層在等第二層的f(n-1)…以此類推,直到最後n==1,最後一層返回1,倒數第二層返回 2*f(1),即f(2),倒數第三層返回3*f(2),即f(3),…直到最後返回f(n)。

具體以f(4)來示範:

紅色箭頭表示每次呼叫函式,綠色箭頭表示當前層結束返回上一層。就好比你先往彈匣裡依次塞入4顆子彈,當最後一顆塞入時,扣動扳機,最後一顆子彈被打出,然後倒數第二顆塞入的上膛。

其實這也能表現出棧的特點之一就是『後進先出』,或者『先進後出』,只有當這一層上面的結束了,這一層才能結束。

能夠理解了,我們稍微總結一下遞迴的特點:

我們再做乙個小練習:

假設有乙個從小到大排列的數字列表,裡面有無數個資料,使用遞迴找到我想要的數字,

data=[1,3,5,9,15,26,47,58,69,89,99,246,368,9854,…]

這裡我們要用二分查詢:

def func(data,num):

if len(data) > 1:

mid = int(len(data)/2)

if num > data[mid]: # 說明num在列表的右半部分

print('%s 在列表的右半部分' % num)

func(data[mid+1:],num) # mid+1表示不將data[mid]算入

elif num < data[mid]: # 說明num在列表的左半部分

print('%s 在列表的左半部分' % num)

func(data[:mid], num) # list顧頭不顧尾

else: # data[mid] == num

print('已找到%s' % num)

else: # list中就乙個數

if data[0] == num:

print('已找到%s' % num)

else:

print('列表中沒有該資料')

其實python中沒有實現這個優化-。-,捎帶提一下,尾遞迴優化是為了提高遞迴的效率,每一次呼叫遞迴都在return 中呼叫。我們知道函式中遇到return都代表函式的結束,那麼在return中呼叫函式本身,只要最後一次呼叫結束,那麼前面的幾次也就都會結束,不會在執行其他的東西。

def func();

return func() # 這就是尾遞迴

def func2():

return n*func2() # 這裡雖然在return中呼叫了函式本身,但最後一層返回後,還是會繼續執行完n*這個事情,並沒有立即結束,所以不是尾遞迴

這裡面有詳細的介紹:

python內建方法介紹

決戰Python之巔(四)

先總體回顧一下第一章的內容 1.三大類程式語言 機器語言 組合語言 高階語言 其中高階語言又分為解釋型 編譯型。2.python的使用者互動 輸入 input 輸出 print。3.注釋 單行使用 多行使用三對單引號 即 4.變數的規範 1.變數名只能是字母 數字或下劃線的任意組合 2.變數名的第乙...

決戰Python之巔(十九) 併發三巨頭之協程

greenlet模組 gevent模組 來來來,複習一下,什麼是程序 執行緒?程序是資源分配的最小單位,執行緒是cpu排程的最小單位。按道理來說我們已經算是把cpu的利用率提高很多了。但是我們知道無論是建立多程序還是建立多執行緒來解決問題,都要消耗一定的時間來建立程序 建立執行緒 以及管理他們之間的...

決戰Python之巔(十三)生成器和迭代器

拖了這麼久才來補生成器和迭代器 之前在講列表的時候並沒有經過這個東西,現在我來介紹一下。列表生成式可以用一句話就能生成乙個列表,如a x for x in range 10 這樣就能直接生成乙個0 9的列表。相對於利用for迴圈 while迴圈來說,更簡單快捷。當然你也可以這樣做b x 2 for ...