在 Python 的
__builtin__
模組中有一些函式,不需要 import
也可以使用,有幾個簡單好用的資料處理函式值得介紹:
range(start, stop[, step])
zip([iterable, ...])
enumerate(sequence, start=0)
reduce(function, iterable[, initializer])
range、zip 與 enumerate
要瞭解這些資料處理函式如何使用,最好的方式就是從練習開始 …練習 6:使用
range
、zip
與 enumerate
在 Python 中,如果想使用
for in
語法來迭代 list
,而且希望取得索引資訊,該如何進行呢?例如,如果有個 list = ['Justin', 'caterpillar', 'openhome']
,想要有以下的顯示結果:
0, Justin
1, caterpillar
2, openhome
先給個小提示,程式基本上可以長這樣:
names = ['Justin', 'caterpillar', 'openhome']
for ______ in ______:
print '{0}, {1}'.format(______)
試著想想,如果使用分別使用
range
、zip
與 enumerate
,那麼程式中三個空白處怎麼寫呢?別忘了,查看一下 range
、zip
與 enumerate
的文件,他們都在 __builtin__
模組的文件中。
別忘了,你可以在 Lab 檔案的 solutions 目錄找到解答。
reduce
__builtin__
中的 reduce
,有時在別的語言中會被稱為 foldLeft,它其實代表了一種高度抽象化後的流程重用,只要是打算從清單中求值的需求,基本上都可以使用它。
舉例來說,如果你想要知道
[1, 2, 3, 4, 5]
的加總,雖然可以直接撰寫迴圈來求值,不過,也可以撰寫為 reduce(lambda sum, elem: sum + elem, [1, 2, 3, 4, 5], 0)
來求值,試試在 Python 互動環境中鍵入,結果會是 15。
初學者會有點難懂
reduce
的原理,可以藉由這段動畫來理解,你也就會知道,為什麼它又在別的語言中,被稱為 foldLeft:
如果 reduce
接受的 lambda
部份,改為一個具體名稱的 add
函式,那麼就可以寫為 為 reduce(add, [1, 2, 3, 4, 5], 0)
,配合上圖,reduce
的運作就像是折紙,從 0 開始,每折一次就與藍色數字進行一次 add
,折完後的結果就是加總值。
這個
reduce
函式很有用,可以有一百萬種用法,只要你想從某個清單中求值,都可以使用 reduce
,只要你依需求給 reduce 要處理的函式與初值。
練習 7:使用
reduce
使用
reduce
與 for
包含式,將以下的範例進行重構,目標是清除所有顯式的迴圈流程:
def ascending(a, b): return a - b
def descending(a, b): return -ascending(a, b)
# selection sort
def sorted(xs, compare = ascending):
return [] if not xs else __select(xs, compare)
def __select(xs, compare):
selected = xs[0]
for elem in xs[1:]:
if compare(elem, selected) < 0:
selected = elem
remain = []
selected_list = []
for elem in xs:
if elem != selected:
remain.append(elem)
else:
selected_list.append(elem)
return xs if not remain else selected_list + __select(remain, compare)
print sorted([2, 1, 3, 6, 5])
print sorted([2, 1, 3, 6, 5], descending)
關於函數式程式設計
想要知道reduce
的原理,可以看看 List 處理模式 中的說明。 實際上,reduce
與 for
包含式的概念源自函數式程式設計(Functional programming),嗯?好像很高深,其實如果你能完成練習 7,你已經做了一次函數式程式設計了。
不過,何時該使用函數式的元素,取決於可讀與風格問題,在 Python 中確實是有那麼一些函數式程式設計的元素,
for
包含式在 Python 中應用的很多,因為可以增加可讀性,然而像 reduce
這種元素,由於可讀性並不好,因而並不太鼓勵去用它,用更具體的函式名稱來封裝 reduce
會更好,以上面的加總來說,可以寫個 sum
函式來表達意圖。實際上,在 Python 3 中,reduce
不再位於 __builtin__
模組,而被移至 funtools
模組了。無論如何,藉由這個練習,瞭解到 Python 可進行多重典範設計,只要你願意的話,函數式是可以的設計之一;接下來的內容,是要介紹 Python 中對永續化(Persistence)的基本支援,順便來看看幾種永續設計方式。