python遞迴函式
什麼是遞迴?
遞迴,就是在函式執行中自己呼叫自己
**示例:
def recursion(n): # 定義遞迴函式
print(n) # 列印n
recursion(n+1) # 在函式的執行種呼叫遞迴
recursion(1) # 呼叫函式
這個函式在不斷的自己呼叫自己,每次呼叫n+1,看下執行結果:
998traceback (most recent call last):
file "d:/py_study/day08-函式/python遞迴函式md/01-什麼是遞迴.py", line 11, in
recursion(1)
file "d:/py_study/day08-函式/python遞迴函式md/01-什麼是遞迴.py", line 9, in recursion
recursion(n+1)
file "d:/py_study/day08-函式/python遞迴函式md/01-什麼是遞迴.py", line 9, in recursion
recursion(n+1)
file "d:/py_study/day08-函式/python遞迴函式md/01-什麼是遞迴.py", line 9, in recursion
recursion(n+1)
[previous line repeated 993 more times]
file "d:/py_study/day08-函式/python遞迴函式md/01-什麼是遞迴.py", line 8, in recursion
print(n)
recursionerror: maximum recursion depth exceeded while calling a python object
process finished with exit code 1
可為什麼執行了900多次就報錯了呢?還說超過了最大遞迴深度限制,為什麼要限制呢?
通俗來講,是因為每個函式在呼叫自己的時候,還沒有退出,佔記憶體,多了肯定會導致記憶體崩潰.
本質上來將,在計算機中,函式呼叫是通過棧(stack)這樣資料結構實現的,每當進入乙個函式呼叫,棧就會加一層棧幀,每當函式返回,棧就會少一層棧幀.由於棧的大小不是無限的,所以,遞迴呼叫次數多了,會導致棧溢位.
我們還可以修改遞迴深度,**如下:
import sys
sys.setrecursionlimit(1500) # 修改遞迴呼叫深度
def cacl(n):
print(n)
cacl(n+1)
cacl(1)
執行結果如下:
1498traceback (most recent call last):
file "d:/py_study/day08-函式/python遞迴函式md/02-修改遞迴深度.py", line 11, in cacl
cacl(n+1)
file "d:/py_study/day08-函式/python遞迴函式md/02-修改遞迴深度.py", line 11, in cacl
cacl(n+1)
file "d:/py_study/day08-函式/python遞迴函式md/02-修改遞迴深度.py", line 11, in cacl
cacl(n+1)
[previous line repeated 995 more times]
file "d:/py_study/day08-函式/python遞迴函式md/02-修改遞迴深度.py", line 10, in cacl
print(n)
recursionerror: maximum recursion depth exceeded while calling a python object
讓我們以最經典的例子說明遞迴
# 計算n! # 相信很多人都學過階乘,比如5! = 5*4*3*2*1 n! = n*(n-1)*(n-2)*...*1,那麼在遞迴中該如何實現呢?
# 1.打好函式的框架
def factorial(n): # 定義乙個計算階乘的函式
pass # 不做任何操作
factorial(3) # 呼叫
# 2.考慮兩種情況,如果n=1,那麼1的階乘就是1了,如果這個傳遞的引數大於1,那麼就需要計算繼承了.
def factorial(n):
if n == 1: # 判斷如果傳遞的引數是1的情況
return 1 # 返回1,return代表程式的終止
res = factorial(1) # res變數來接受函式的返回值
print(res) # 列印
2.1如果傳遞的引數不是1,怎麼做?
def factorial(n):
if n == 1:
return 1
else:
# 5*4! = 5*4*3! = 5*4*3*2!
return n * factorial(n-1) # 傳遞的引數是n,那麼再次呼叫factorial(n-1)
res = factorial(1)
print(res)
舉例2:
# 讓10不斷除以2,直到0為止。
int(10/2) = 5
int(5/2) = 2
int(2/2) = 1
int(1/2) = 0
# 1.同樣第一步先打框架
def cacl(n): # 定義函式
pass
cacl(10)
# 2.那麼我們想從10開始列印然後一直到0,怎麼做?
def cacl(n): # 定義函式
print(n)
cacl(10)
# 3.已經把列印的值傳遞進去了,那麼就是在裡面操作了
def cacl(n): # 定義函式
print(n) # 列印傳遞進去的值
v = int(n /2) # n/2
if v>0: # 如果v還大於0
cacl(v) # 遞迴,把v傳遞進去
print(n) # 列印v,因為已經呼叫遞迴了,所以此時的n是v
cacl(10)
執行結果如下:
怎麼輸出會是這樣呢?我剛剛說過,什麼是遞迴?遞迴就是在乙個函式的內部呼叫函式本身,我們打個比方,遞迴一共有3層,那麼第二層就是呼叫第一層的結果,第三層又去呼叫第二層的結果,所以!當上面這個程式執行時,第一次列印的是10,然後除上2,等於是5,再繼續除,一直到了1,然後1/2是等於0的,此時就沒有呼叫了遞迴,但是我還在呼叫上一層函式,就需要把這個數給返回出來,所以就變成後來的1,2,5,10了。
遞迴特性
1.必須要有乙個明確的結束條件, 否則就變成死迴圈導致棧溢位
2.每次進入更深一層遞迴時,問題規模相比上次遞迴都應有所減少,這句話的以上就是說,每進入一次遞迴,就會解決一些東西,資料量就會越來越小,最終解決了所有的問題,如果進入一次遞迴沒有解決問題,那麼不管遞迴多少層都沒有意義,直到導致棧溢位。
3.遞迴效率比較低,遞迴層次過多會導致棧溢位,意思是:每當進入一次函式呼叫,棧就會加一層棧幀,每當函式返回,就減少一層棧幀,由於棧不是無限大小的,所以,遞迴呼叫的次數過多,會導致棧溢位。
那麼有沒有優化方式呢?肯定是有的
尾遞迴我在知乎上找了乙個特別有意思的例子來說明下什麼是尾遞迴:
def story() {
從前有座山,
山上有座廟,
廟裡有個老和尚,
def story() {
從前有座山,
山上有座廟,
廟裡有個老和尚,
def cal(n):
print(n)
return cal(n+1) # return代表函式的結束
cal(1) # 這個會一直列印,直到導致棧溢位
# 呼叫下一層的同時,自己就退出了
函式遞迴(例項)
遞迴 函式自己呼叫自己 函式一旦進入遞迴,可能需要很多次呼叫才能遞迴結束。呼叫關係會非常複雜 由於是同乙個函式呼叫自己,每次呼叫執行的 都很相似,涉及到的區域性變數的名字也都一樣,就會特別容易讓人混淆。先舉乙個簡單的例子 求n的階乘 如下 示例 include include 這是求階乘的普通做法 ...
python靜態遞迴函式 python遞迴函式
一 遞迴的定義 1.什麼是遞迴 在乙個函式裡在呼叫這個函式本身 2.最大遞迴層數做了乙個限制 997,但是也可以自己限制 1 deffoo 2 print n 3 n 1 4 foo n 5 foo 1 驗證997 3.最大層數限制是python預設的,可以做修改,但是不建議你修改。因為如果用997...
python靜態遞迴函式 python 遞迴函式
前言 本篇關於遞迴基本借鑑下面部落格講解加入自己理解。1.遞迴函式定義 如果乙個函式在函式內部呼叫自己,那這個函式就是遞迴函式。如 defsum arg,stop print arg if arg arg arg sum arg,stop sum 1,20 2.遞迴的特性 1 必須有乙個明確的結束條...