1. 程式人生 > >每天一點——python map()和reduce()

每天一點——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)》)。

map-一個seq

可以看出,seq中的每個元素都經過了func函式的作用,得到了func(seq[n])組成的列表。

下面舉一個例子進行說明。假設我們想要得到一個列表中數字%3的餘數,那麼可以寫成下面的程式碼。

Python函數語言程式設計之map使用(一個seq) Python
123456# 使用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執行如下圖所示的過程:

map-多個seq

也就是說每個seq的同一位置的元素在執行過一個多元的func函式之後,得到一個返回值,這些返回值放在一個結果列表中。

下面的例子是求兩個列表對應元素的積,可以想象,這是一種可能會經常出現的狀況,而如果不是用map的話,就要使用一個for迴圈,依次對每個位置執行該函式。

Python函數語言程式設計之map使用(多個seq)Python
1 printmap(lambdax,y:x*y,[1,2,3],[4,5,6])# [4, 10, 18]

上面是返回值是一個值的情況,實際上也可以是一個元組。下面的程式碼不止實現了乘法,也實現了加法,並把積與和放在一個元組中。

Python函數語言程式設計之map使用(多個seq) Python
1printmap(lambdax,y:(x*y,x+y),[1,2,3],[4,5,6])# [(4, 5), (10, 7), (18, 9)]

還有就是上面說的func是None的情況,它的目的是將多個列表相同位置的元素歸併到一個元組,在現在已經有了專用的函式zip()了。

Python函數語言程式設計之map使用(func為None)Python
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函式的工作過程圖:

reduce

舉個例子來說,階乘是一個常見的數學方法,Python中並沒有給出一個階乘的內建函式,我們可以使用reduce實現一個階乘的程式碼。

Python函數語言程式設計之reduce使用 Python
12n=5printreduce(lambdax,y:x*y,range(1,n+1))# 120

那麼,如果我們希望得到2倍階乘的值呢?這就可以用到init這個可選引數了。

Python函數語言程式設計之reduce使用Python
1 2 3 m=2 n=5 printreduce(lambdax,y:x*y,range(1,n+1),m)# 240