python递归函数的意思_Python 递归函数
一、函數執行流程
示例.png
全局幀中生成 foo1、foo2、foo3、main 函數對象
main 函數調用
main 中查找內建函數 print 壓棧,將常量字符串壓棧,調用函數,彈出棧頂
main 中全局查找函數 foo1 壓棧,將常量 100、101 壓棧,調用函數 foo1,創建棧幀。print 函數壓棧,字符串和變量 b、b1 壓棧,調用函數,彈出棧頂,返回值
main 中全局查找函數 foo2 壓棧,將常量 200 壓棧,調用函數 foo2,創建棧幀。foo3 函數壓棧,變量 c 引用壓棧,調用 foo3,創建棧幀。foo3 完成 print 函數調用后返回。foo2 恢復調用,執行 print 后,返回值。main 中 foo2 調用結束彈出棧頂。main 繼續執行 print 函數調用,彈出棧頂。main 函數返回
示例.png
示例.png
二、遞歸 Recursion
函數直接或見著調用自身就是 遞歸
遞歸需要有邊界條件、遞歸前進段、遞歸返回段
遞歸一定要有 邊界條件
當邊界條件不滿足的時候,遞歸前進
當邊界條件滿足的時候,遞歸返回
示例.png
2.1 斐波那契數列 Fibonacci number:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ....
若 F(n) 為該數列第 n 項(n∈N*),那么這句話可寫成:F(n)=F(n-1)+F(n-2)
F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2)
a = 0
b = 1
n = 10 # 55
# 循環實現
for i in range(n -1):
a, b = b, a + b
else:
print(b)
# 遞歸實現
def fib(n):
return 1 if n < 3 else fib(n-1) + fib(n-2)
fib(5) 解析
fib(4) + fib(3)
fib(4) 調用 fib(3)、fib(2)
fib(3) 調用 fib(2)、fib(1)
fib(2)、fib(1) 是邊界 return 1,所有函數調用逐層返回
2.2 遞歸要求
遞歸一定要有退出條件,遞歸調用一定要執行到這個退出條件。沒有退出條件的遞歸調用,就是無限調用
遞歸調用的深度不宜過深
Python 對遞歸調用的深度做了限制,以保護解釋器
超過遞歸深度限制,拋出 RecursionError: maxinum recursion depth exceeded 超出最大深度
sys.getrecursionlimit()
2.3 遞歸性能 fib(35) 比較
for 循環
示例.png
遞歸
示例.png
2.4 遞歸的性能
循環稍微復雜一些,但是只要不是死循環,可多次迭代直至算出結果
fib 函數代碼極簡易懂,但是只能獲取到最外層函數調用,內部遞歸結果都是中間結果。而且給定一個 n 都要進行近 2n 次遞歸,深度越深,效率越低。為了獲取斐波那契數列需要外面再套一個 n 次循環,效率就更低了
遞歸還有深度限制,若遞歸復雜,函數反復壓棧,棧內存很快就溢出了
斐波那契數列改進
def fib(n, a=0, b=1):
a, b = b, a+b
if n == 1:
return a
return fib(n-1, a, b)
print(fib(4))
改進后的函數和循環的思想類似
參數 n 是邊界條件,用 n 來計數
上次的計算結果直接作為函數的實參
效率高
和循環比較,性能相近。所以并不是說遞歸一定效率低下,但遞歸有深度限制
2.5 間接遞歸
def foo1():
foo2()
def foo2():
foo1()
foo1()
間接遞歸,是通過別的函數調用了函數自身
拖構成了循環遞歸調用是非常危險的,但往往這種情況在代碼復雜情況下,很可能發生這種調用,要用代碼的規范來避免遞歸調用的發生
三、遞歸總結
遞歸是一種很自然的表達,符合邏輯思維
遞歸相對運行效率低,每一次調用函數都要開辟棧幀
遞歸有深度限制,若遞歸層次太深,函數反復壓棧,棧內存很快就溢出了
若是有限次數的遞歸,可使用遞歸調用,或使用循環代替,循環代碼稍復雜一些,但只要不是死循環,可多次迭代直至算出結果
絕大多數遞歸,都可使用循環實現
即使遞歸代碼很簡潔,但 能不用則不用 遞歸
四、遞歸練習
4.1 求 n 的階乘
按公式
def fac(n):
if n == 1:
return 1
return n * fac(n-1)
def fac(n):
return 1 if n < 2 else n * fac(n-1)
按循環
n = 6
fac = 1
for i in range(n, 0, -1): # 計數器 n 次
fac = fac * i
print(fac)
def fac1(n, fac=1):
fac = fac * n
if n == 1:
return fac
return fac1(n-1, fac)
4.2 將一個數逆序放入列表中,例如 1234 => [4, 3, 2, 1]
傳入字符串
target = []
def revert(data):
target.append(data[-1])
if len(data) == 1:
return target
return revert(data[:-1])
revert('1234')
def revert(data, target=None):
if target is None:
target = list()
target.append(data[-1])
if len(data) == 1:
return target
return revert(data[:-1], target)
revert('1234')
def revert(data):
if data == '':
return []
return [data[-1]] + revert(data[:-1])
revert('1234')
傳入數字
def revert(data, target=None):
if target is None:
target = list()
if not isinstance(target, list):
return
x, y = divmod(data, 10)
target.append(y)
if x:
return revert(x, target)
return target
revert(120340)
4.3 解決猴子吃桃問題
按題意
def peach(days=1):
if days == 10:
return 1
return 2 * (peach(days+1) +1)
def peach(days=10):
if days == 1:
return 1
return 2 * (peach(days-1) + 1)
按循環
peach = 1
for i in range(9):
peach = 2 * (peach + 1)
print(peach)
def fn(days=9, peach=1):
peach = 2 * (peach + 1)
if days == 1:
return peach
return fn(days-1, peach)
fn()
總結
以上是生活随笔為你收集整理的python递归函数的意思_Python 递归函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TOGAF架构开发方法(ADM)之技术架
- 下一篇: format函数python是什么意思,