斐波那契數列-python實現


斐波那契數列(黃金分割數列)指的是這樣一個數列 0, 1, 1, 2, 3, 5, 8, 13,特別指出:第0項是0,第1項是第一個1。從第三項開始,每一項都等於前兩項之和。
 
Python 實現斐波那契數列代碼如下:
實現一:
 1 def fibonacci():
 2     num = input("Please input your number\n")
 3     i,a,b= 0,0,1           //賦值
 4     if int(num) < 0:
 5         print("你輸入的數據不合理")
 6     elif int(num)== 1:
 7         print(a)
 8     else:
 9         while i < int(num):
10             print(a)
11             #sum  = a+b
12             #a = b
13             #b = sum
14             a, b = b, a + b  #a, b = b, a + b這里不能寫成 a=b   b=a+b,如果寫成這樣,b就不是前兩位相加的值,而是已經被b賦過值的a和b相加的值
15             i+=1
16 fibonacci()
實現二:
    使用列表的方式實現
1 def fibonacci(num):
2     fibs = [0,1]
3     for i in range(num-2):
4         fibs.append(fibs[-2]+fibs[-1])   #倒數第二個+倒數第一個數的結果,追加到列表
5     print(fibs)
6     
7 fibonacci(5)
實現三:
    以上兩種方式,都是直接調用的函數中的print打印,return值為none,因此無法進行復用。
    將return為一個序列,可以直接復用該序列。
1 def fibonacci(num):
2     fibs = [0,1]
3     for i in range(num-2):
4         fibs.append(fibs[-2]+fibs[-1])   #倒數第二個+倒數第一個數的結果,追加到列表
5     return(fibs)
6 fibonacci(5)

或者

1 def fab_demo2(max):
2     a, n, b = 0, 0, 1
3     list_demo = []
4     while n < max:
5         list_demo.append(b)
6         a, b = b, a + b
7         n += 1
8     print(list_demo)
9     return list_demo
實現四:
    可以復用了,但是考慮到后期若要存儲在list中的數據量過大,比較吃內存浪費資源,應該怎么辦呢,
    此時,考慮到利用 iterable 我們可以把 fab 函數改寫為一個支持 iterable 的 class
 1 class Fab(object):
 2     def __init__(self,max):
 3         self.max = max
 4         self.n ,self.a ,self.b = 0 ,0 ,1
 5 
 6     def __iter__(self):        #繼承object,重寫__iter__后,自動調用__next__方法,返回r對象
 7         return self
 8 
 9     def __next__(self):        #此處python2為next,python3為__next__,注意區別
10         if self.n < self.max:
11             r = self.b
12             self.a , self.b = self.b , self.a + self.b
13             self.n += 1
14             return r      
15         raise StopIteration()
16 #Fab 類通過 next() 不斷返回數列的下一個數,內存占用始終為常數:
17 for i in Fab(5):
18     print(i)
19 #或者
20 print(next(iter(Fab(5)))) 

實現五

代碼不夠簡潔,使用yield關鍵字

 1 def fab_demo4(max):
 2     a,n,b = 0,0,1
 3     while n < max:
 4         yield  b
 5         #print b
 6         a,b = b,a+b
 7         n+=1
 8 print(next(fab_demo4(5)))
 9 for i in fab_demo4(5):
10     print(i)
 
僅僅把 print b 改為了 yield b,就在保持簡潔性的同時獲得了 iterable 的效果
yield 的作用就是把一個函數變成一個 generator,帶有 yield 的函數不再是一個普通函數,Python 解釋器會將其視為一個 generator,
調用 fab(5) 不會執行 fab 函數,而是返回一個 iterable 對象!
在 for 循環執行時,每次循環都會執行 fab 函數內部的代碼,執行到 yield b 時,fab 函數就返回一個迭代值,
下次迭代時,代碼從 yield b 的下一條語句繼續執行,而函數的本地變量看起來和上次中斷執行前是完全一樣的,於是函數繼續執行,直到再次遇到 yield。
 
也可以手動調用 fab(5) 的 next() 方法(因為 fab(5) 是一個 generator 對象,該對象具有 next() 方法)

我們可以得出以下結論:

一個帶有 yield 的函數就是一個 generator,它和普通函數不同,生成一個 generator 看起來像函數調用,但不會執行任何函數代碼,直到對其調用 next()(在 for 循環中會自動調用 next())才開始執行。雖然執行流程仍按函數的流程執行,但每執行到一個 yield 語句就會中斷,並返回一個迭代值,下次執行時從 yield 的下一個語句繼續執行。看起來就好像一個函數在正常執行的過程中被 yield 中斷了數次,每次中斷都會通過 yield 返回當前的迭代值。

yield 的好處是顯而易見的,把一個函數改寫為一個 generator 就獲得了迭代能力,比起用類的實例保存狀態來計算下一個 next() 的值,不僅代碼簡潔,而且執行流程異常清晰。

如何判斷一個函數是否是一個特殊的 generator 函數?可以利用 isgeneratorfunction 判斷:

1 >>> from inspect import isgeneratorfunction
2 >>> isgeneratorfunction(fab)
3 True

要注意區分 fab 和 fab(5),fab 是一個 generator function,而 fab(5) 是調用 fab 返回的一個 generator,好比類的定義和類的實例的區別:

 


免責聲明!

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



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