每天一點——python map()和reduce()
轉自:http://www.pythoner.com/46.html
今天要介紹的是Python函數語言程式設計中的另外兩個內建函式map()
和reduce()
,而不是Google的MapReduce。
1.map()
格式:map( func, seq1[, seq2...] )
Python函數語言程式設計中的map()
函式是將func作用於seq中的每一個元素,並用一個列表給出返回值。如果func為None,作用同zip()
。
當seq只有一個時,將func函式作用於這個seq的每個元素上,得到一個新的seq。下圖說明了只有一個seq的時候map()函式是如何工作的(本文圖片來源:《Core Python Programming (2nd edition)》)。
可以看出,seq中的每個元素都經過了func函式的作用,得到了func(seq[n])組成的列表。
下面舉一個例子進行說明。假設我們想要得到一個列表中數字%3的餘數,那麼可以寫成下面的程式碼。
Python函數語言程式設計之map使用(一個seq) Python123456 | # 使用mapprintmap(lambdax:x%3,range(6))# [0, 1, 2, 0, 1, 2]#使用列表解析print[x%3forxinrange(6)]# [0, 1, 2, 0, 1, 2] |
這裡又和上次的filter()
一樣,使用了列表解析的方法代替map執行。那麼,什麼時候是列表解析無法代替map的呢?
原來,當seq多於一個時,map可以並行地對每個seq執行如下圖所示的過程:
也就是說每個seq的同一位置的元素在執行過一個多元的func函式之後,得到一個返回值,這些返回值放在一個結果列表中。
下面的例子是求兩個列表對應元素的積,可以想象,這是一種可能會經常出現的狀況,而如果不是用map的話,就要使用一個for迴圈,依次對每個位置執行該函式。
Python函數語言程式設計之map使用(多個seq)Python1 | printmap(lambdax,y:x*y,[1,2,3],[4,5,6])# [4, 10, 18] |
上面是返回值是一個值的情況,實際上也可以是一個元組。下面的程式碼不止實現了乘法,也實現了加法,並把積與和放在一個元組中。
1 | printmap(lambdax,y:(x*y,x+y),[1,2,3],[4,5,6])# [(4, 5), (10, 7), (18, 9)] |
還有就是上面說的func是None的情況,它的目的是將多個列表相同位置的元素歸併到一個元組,在現在已經有了專用的函式zip()
了。
1 2 3 | printmap(None,[1,2,3],[4,5,6])# [(1, 4), (2, 5), (3, 6)] printzip([1,2,3],[4,5,6])# [(1, 4), (2, 5), (3, 6)] |
需要注意的是,不同長度的多個seq是無法執行map函式的,會出現型別錯誤。
2.reduce()
格式:reduce( func, seq[, init] )
reduce函式即為化簡,它是這樣一個過程:每次迭代,將上一次的迭代結果(第一次時為init的元素,如沒有init則為seq的第一個元素)與下一個元素一同執行一個二元的func函式。在reduce函式中,init是可選的,如果使用,則作為第一次迭代的第一個元素使用。
簡單來說,可以用這樣一個形象化的式子來說明:reduce( func, [1, 2,3] ) = func( func(1, 2), 3)
下面是reduce函式的工作過程圖:
舉個例子來說,階乘是一個常見的數學方法,Python中並沒有給出一個階乘的內建函式,我們可以使用reduce實現一個階乘的程式碼。
Python函數語言程式設計之reduce使用 Python12 | n=5printreduce(lambdax,y:x*y,range(1,n+1))# 120 |
那麼,如果我們希望得到2倍階乘的值呢?這就可以用到init這個可選引數了。
Python函數語言程式設計之reduce使用Python1 2 3 | m=2 n=5 printreduce(lambdax,y:x*y,range(1,n+1),m)# 240 |