跳转到内容

BOO入門/Generators

维基教科书,自由的教学读本

BOO入門 > Generators (上一章:將函數當作物件與多執行緒 下一章:巨集)


Generator運算式

[编辑]
定義 定義 Generator運算式:以語法:<expression> for <declarations> [as <type>] in <iterator> [if|unless <condition>] 建立 generator 的語句。

Generator運算式很類似我們之前提過的 for 迴圈,也具有相似的作用。 學習如何使用 Generator運算式的方法就是從例子裡來學,所以請開啟 booish:

$ booish
>>> List(x for x in range(5)) // 最簡單的 Generator 運算式
[0, 1, 2, 3, 4]
>>> List(x * 2 for x in range(5)) // 取得數值的兩倍
[0, 2, 4, 6, 8]
>>> List(x**2 for x in range(5)) // 取得數值的平方
[0, 1, 4, 9, 16]
>>> List(x for x in range(5) if x % 2 == 0) // 將所有偶數取出來
[0, 2, 4]
>>> List(x for x in range(10) if x % 2 == 0) // 將所有偶數取出來
[0, 2, 4]
>>> List(y for y in (x**2 for x in range(10)) if y % 3 != 0) // Generator運算式裡的Generator運算式
[1, 4, 16, 25, 49, 64]
>>> List(cat.Weight for cat in myKitties if cat.Age >= 1.0).Sort()  // 譯註,你會在這行遇到錯誤,請參考後面的說明。
[6.0, 6.5, 8.0, 8.5, 10.5]
>>> genex = x ** 2 for x in range(5)
generator(System.Int32)
>>> for i in genex:
...     print i
...
0
1
4
9
16

貓體重的範例(cat-weight),如你所見,很容易就能找到符合條件的小貓。(譯註:這行無法運作,因為你沒有 myKitties,如果要讓這行能運行,請自己宣告一個類別,並加入 Weight、Age 屬性,接著製作一個串列,放入數個這個類別的實體(object)。)

你不需要額外建立新串列,然後再一個一個去比對、放到新串列裡。

generators 繼承自 IEnumerable,所以你可以很容易地用迴圈去尋訪。

建議 建議 別用的太過火啦。如果他們讓你代碼不容易閱讀的話,試著稍微擴展一下。(譯註:簡單的說,就是稍微想一下要怎麼寫會比較容易讓人了解的意思。具體的方法有很多,例如使用 for 迴圈或是下一節介紹的 Generator方法 ...)

Generator方法

[编辑]
定義 定義 Generator方法:在方法裡使用 yield 關鍵字來建立 Generator 的方法。

Generator方法是一個能讓你回傳多次的正規作法。

這裡有個 Generator方法能傳回 2 的指數。

// Generator方法的範例
def TestGenerator():
    i = 1
    yield i
    for x in range(10):
        i *= 2
        yield i

print List(TestGenerator())

輸出結果

[1, 2, 4, 8, 16, 32, 64, 128, 512, 1024]

Generator方法很有威力,因為能在 yield 之後在記憶體裡保存所有的區域變數。這在其他語言也能見到(C# 裡稱為 Iterator,python 裡也稱為 Generator)。

總而言之,很有用。

練習

[编辑]
  1. 試著用Generator方法來作 fibonacci 數列。

課外參考

[编辑]