Python中lambda、zip、map、reduce函數的使用

一、lambda表達式

lambda表達式,通常是在需要一個函數,但是又不想費神去命名一個函數的場合下使用,也就是指匿名函數。lambda所表示的匿名函數的內容應該是很簡單的,如果複雜的話,乾脆就重新定義一個函數了,使用lambda就有點過於執拗了。lambda就是用來定義一個匿名函數的,如果還要給他綁定一個名字的話,就會顯得有點畫蛇添足,通常是直接使用lambda函數。如下所示:

<調用名> = lambda <參數1>,<參數2>...:<表達式>
add = lambda x,y:x+y
add(1,2)  # 結果爲3

二、zip()函數用法

zip()是Python的一個內建函數,它接受一系列可迭代的對象作爲參數,將對象中對應的元素打包成一個個tuple(元組),然後返回由這些tuples組成的list(列表)。若傳入參數的長度不等,則返回list的長度和參數中長度最短的對象相同。利用*號操作符,可以將list unzip(解壓),看下面的例子就明白了:

>>> a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b)
[(1, 4), (2, 5), (3, 6)]
>>> zip(a,c)
[(1, 4), (2, 5), (3, 6)]
>>> zip(*zipped)
[(1, 2, 3), (4, 5, 6)]

對於這個並不是很常用函數,下面舉幾個例子說明它的用法:

2.1、維矩陣變換(矩陣的行列互換)

比如我們有一個由列表描述的二維矩陣
a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
通過python列表推導的方法,也能輕易完成這個任務

print [ [row[col] for row in a] for col in range(len(a[0]))]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

另外一種讓人困惑的方法就是利用zip函數:

>>> a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> zip(*a)
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
>>> map(list,zip(*a))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

這種方法速度更快但也更難以理解,將list看成tuple解壓,恰好得到我們“行列互換”的效果,再通過對每個元素應用list()函數,將tuple轉換爲list

三、Python函數式編程 map()、reduce()

3.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)

1

2

3

4

5

6

# 使用map

print map( lambda x: x%3, range(6) )  # [0, 1, 2, 0, 1, 2]

 

#使用列表解析

print [x%3 for x in range(6)]  # [0, 1, 2, 0, 1, 2]

 

這裏又和上次的filter()一樣,使用了列表解析的方法代替map執行。那麼,什麼時候是列表解析無法代替map的呢?

原來,當seq多於一個時,map可以並行地對每個seq執行如下圖所示的過程:

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

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

Python函數式編程之map使用(多個seq)

1

print map( lambda x, y: x * y, [1, 2, 3], [4, 5, 6] )  # [4, 10, 18]

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

Python函數式編程之map使用(多個seq)

1

print map( lambda x, y: ( x * y, x + y), [1, 2, 3], [4, 5, 6] )  # [(4, 5), (10, 7), (18, 9)]

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

Python函數式編程之map使用(func爲None)

1

2

3

print map( None, [1, 2, 3], [4, 5, 6] )  # [(1, 4), (2, 5), (3, 6)]

 

print zip( [1, 2, 3], [4, 5, 6] )  # [(1, 4), (2, 5), (3, 6)]

需要注意的是,不同長度的多個seq是無法執行map函數的,會出現類型錯誤。

3.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使用

1

2

n = 5

print reduce(lambda x, y: x * y, range(1, n + 1))  # 120

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

Python函數式編程之reduce使用

1

2

3

m = 2

n = 5

print reduce( lambda x, y: x * y, range( 1, n + 1 ), m )  # 240

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章