Python中由生成杨辉三角代码所思考的一些问题
楊輝三角定義如下:
1/ \1 1/ \ / \1 2 1/ \ / \ / \1 3 3 1/ \ / \ / \ / \1 4 6 4 1/ \ / \ / \ / \ / \ 1 5 10 10 5 1把每一行看做一個list,試寫一個generator,不斷輸出下一行的list。
該題目考查生成器的應用。一般的思路是,首先在每一行輸出一個1,隨后通過循環,位置i(從2開始)的數是上一行i與i-1位置的數之和,當i與上一行數字個數相同時,循環終止,最后再添加進一個1,形成新的一行。
基于這個基本思路,將python的生成器運用到里面,有兩種常見的寫法:
一種寫法如下:
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' def triangles():#楊輝三角的一種生成方法l = [1]while True : yield lfor i in range ( 1,len (l) ) :l [i] = h [i] + h [i-1] l.append (1)h = l[:]另外一種寫法如下,運用了list的生成式:
def triangles():l = [1] while True :yield ll = [1] + [ l[i] + l[i+1] for i in range ( len (l) - 1)] + [1]可以看到,以上兩種寫法都是相當簡潔的。一開始這兩個代碼看不太懂,比如說為啥第一種寫法里一開始h里面沒有數,卻也能夠正常執行?主要是對于生成器的yield機制不明白,以及對于range的用法不是特別清楚。以下就這兩點分別解釋。
首先,當函數中出現了yield之后,該函數就不再被視為函數,而視為一個生成器。此時,整個函數被使用的語句流程會發生改變,一般的函數都是調用的時候從函數入口進,發現return或函數執行完畢后返回,而生成器函數則是每次調用函數執行,執行到yield返回,下次再調用函數的時候從上次yield返回處繼續執行。
其次,range的用法中是,如果是【range(x,x) 其中x是常量】的形式,range依然返回空。故在上述代碼的for循環中,由于在第一次試圖循環的時候,后面的range要么是range(1,1)要么是range(0),故都會成功避開i或者h沒有實際值的循環,執行接下來的部分。當第二次試圖循環開始時,i和h內的內容都已經滿足條件了,所以就能正常運行了。
還有一種我看到的最簡單的寫法:
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! '''def triangles():L = [1]while True:yield LL= [(L + [0])[i] + ([0] + L)[i] for i in range(len(L)+1)]這一種寫法直接去掉了第二種寫法里每次L兩邊額外插入的[1],使其變為了一個完整的一個list生成式,可以說是相當精妙。
那么,這種寫法為什么也可以呢?我們再來分析一下楊輝三角的性質,這樣,為了直觀理解,我們先利用上面的代碼,舉一個運行中的過程例子。
比如,L此時為[1,1](楊輝三角第二行),現在需要求第三行。根據第五行的生成式,將按照以下步驟進行計算:
L尾部加0,得到[1,1,0],我們稱之為tempL1
L首部加0,得到[0,1,1],我們稱之為tempL2
現在,根據之后的for循環,L最終要被賦值成由tempL1與tempL2對應的每個相同位置數字之和所組成的列表,經過計算,這個新的L應該為[1,2,1]。居然確實是楊輝三角的第三行!
相信聰明的觀眾已經明白了,這個最簡單的寫法是利用了楊輝三角本身的對稱性質,讓同一行錯開一位豎式相加,得到的就是下一行的結果。
同時,利用python里面本身就極為方便的列表擴展寫法和列表生成式,才有了第三種如此簡潔的寫法~
總結
以上是生活随笔為你收集整理的Python中由生成杨辉三角代码所思考的一些问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python用HTMLTestRunne
- 下一篇: python中的del,remove,p