python之路第五篇之遞歸(進階篇:續:經典例子剖析)


遞歸

在函數內部,可以調用其他函數;
如果一個函數在內部調用自身本身,這個函數就是遞歸函數。

例如,我們來計算階乘:

n! = 1 x 2 x 3 x ... x n,

用函數f1(n)表示,可以看出:

f1(n) = n! = 1 x 2 x 3 x ... x (n-1) x n 
      = (n-1)! x n = f1(n-1) x n

所以,f1(n)可以表示為 n x f1(n-1),只有n=1時需要特殊處理。
於是,f1(n)用遞歸的方式寫出來就是:

def f1(n):
  if n==1:
    return 1
  return n * f1(n - 1)

上面就是一個遞歸函數。執行結果如下:

>>> f1(1)
1
>>> f1(3)
6
>>> f1(10)
3628800

那么,利用函數編寫如下數列:

斐波那契數列指的是這樣一個數列 
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,
610,987,1597,2584,4181,6765,10946,17711,28657,46368 ...

實現代碼如下:

def func(arg1,arg2):
    if arg1 == 0:
        print arg1, arg2
    arg3 = arg1 + arg2
    print arg3
    func(arg2, arg3)

func(0,1)

執行結果如下:(“....”代表省略)

.....
26863810024485359386146727202142923967616609318986952340123175997617981700247881689338369654483356564191827856161443356312976673642210350324634850410377680367334151172899169723197082763985615764450078474174626
	Traceback (most recent call last):
.....
334151172899169723197082763985615764450078474174626
Traceback (most recent call last):
File "<stdin>", line 1, in <module>  #有報錯
......

為什么上面有報錯,難道是程序錯了?其實不是,程序沒錯,因為“斐波那契數” 規律是前兩個數相加
等於后面一個數,而程序一直不斷這樣執行下去,最終達到系統默認臨界值,當然程序也就出錯了

接下來,我們把程序再改改,我們讓“不斷循環的第三個值”(即arg3)大於1000的時候 返回一個值,
看看這個時候的效果,直接看下面代碼:

def func1(arg1,arg2):
    if arg1 == 0:
        #print arg1,arg2
        pass
    arg3 = arg1 + arg2
    if arg3 > 1000:
        return arg3
    func1(arg2,arg3)

result = func1(0,1)
print result

你們覺得上面打印的結果是什么?

看下面執行結果:

>>> print result
None

這是為什么,苦苦熬了這么多年,終於等到你,>~< ...(哈哈,開個玩笑)

上面代碼分解如下:

def func1(arg1,arg2):   
#arg1 = 0 ,arg2 = 1,第2次:arg1 = 1,arg2 = 1,第3次:arg1 = 1,arg2 = 2,
第4次:arg1 = 2,arg2 = 3,
    
    if arg1 == 0:       #滿足條件,開始執行 
        #print arg1,arg2
        pass            #不做任何處理
    
    arg3 = arg1 + arg2  #走到這一步,arg3 = 0 + 1 = 1,第2次:arg3 = 1 + 1 = 2,
    第3次,arg3 = 1 + 2 = 3,第4次:arg3 = 2 + 3 = 5, .... 執行到第18次....
    
    if arg3 > 1000:     #第一次循環不符合條件,繞開return arg3,而繼續往下執行;....
    假設執行到第18次時符合條件,那么就會執行下面的代碼,即 return arg3 會被執行!!!
        
        return arg3     
      #第一次循環不執行,2,3,4次都一樣不執行;.....,假設第18次時符合條件,並且執行
      了return arg3,重點來了!!!!,這個時候我們都知道,函數體中,一個值被return,
      那么這個函數的生命周期也就結束,不再往下執行,也就意味着下面的func1(arg2,arg3)
      沒有被執行. 	    
    
    func1(arg2,arg3)    
    #自身調用第2個和第3個的值,即第1次為:1 ,1  第2次為1,2,第3次:2,3 第4次:3,5 ....
    假設執行到第18次,這個時候沒有被執行,因為上面return的出現,函數生命周期已經結束
    (重點!!:分析:既然18次時符合條件,並且return arg3,函數直接出去了,大家不妨想想,
    那么在出去之前,它的上一次執行,也就是第17次並沒有在func1(arg2,arg3)這一步,將這個
    函數的值return(返回)給func1(arg1,arg2),也就意味着,17次沒有返回,而18次時,
    函數生命周期也已經結束!之后執行函數外面的操作,result = func1(arg1,arg2),print result,
    接着往下看:
        
大家都知道,如果要將一個函數賦值給一個變量,假設這么賦值:result = func1(“值”,“值”),
那么這個函數肯定會有一個返回值,同時賦值給這個變量,由於17次沒有return func1(arg2,
arg3)給func1(arg1,arg2),18次時函數結束,那么這個函數的默認返回值就是None(即空值)
那么賦值給這個變量和打印這個變量也就是None

同時大家記住一句話:python 函數默認是從上往下執行

	
result = func1(0,1)  #第一次開始執行,賦值!第18次賦值,這個時候是None
print result         #第1,2,3,4都不執行,因為這個是在函數外,只有函數結束后才行,....
第18次,這里打印了最終值"None"

大家是否已經知道

上面的代碼改成下面這樣:

def func1(arg1,arg2):
    if arg1 == 0:
    #print arg1,arg2
        pass
    arg3 = arg1 + arg2
    if arg3 > 1000:
        return arg3
    return func1(arg2,arg3)   #這里return ,所有有值

執行結果如下:

>>> result = func1(0,1)
>>> print result
1597

return 返回值(經典例子):

你們認為下面的result 結果是什么? 10000???NO,NO,NO

def n4():
	return "10000"
def n3():
	n4()
def n2():
	n3()
def n1():
	n2()

result = n1()
print result

返回值為None

為什么?

請聽分解:當我們最終print result 時,result = n1(), n1函數調用n2, n2函數調用n3,
n3函數調用n4,而當n3調用n4時,(n4函數有返回值),並沒有return n4(),意味着n3是None,
因此n2函數在調用n3時,由於n3是None,,同時n3本身也沒有return給n2,(就算return給n2了,
也是None,哈哈)所以最終返回就是None

這個例子是不是很經典?好了,今天很晚了,就分享到這里,因為白天上班,沒什么時間寫,也就只能晚上
寫了(ps,現在是凌晨2點18分),下次繼續新的內容!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM