python中的zip、map、reduce 、lambda、filter函數的使用

飛機票html

lambda函數python

lambda只是一個表達式,函數體比def簡單不少。編程

lambda的主體是一個表達式,而不是一個代碼塊。僅僅能在lambda表達式中封裝有限的邏輯進去。函數式編程

lambda表達式是起到一個函數速寫的做用。容許在代碼內嵌入一個函數的定義。函數

以下例子:spa

定義了一個lambda表達式,求三個數的和。code

再看一個例子:htm

用lambda表達式求n的階乘。對象

------------------------------blog

lambda表達式也能夠用在def函數中。

看例子:

這裏定義了一個action函數,返回了一個lambda表達式。其中lambda表達式獲取到了上層def做用域的變量名x的值。

a是action函數的返回值,a(22),便是調用了action返回的lambda表達式。

這裏也能夠把def直接寫成lambda形式。以下

zip()函數用法

 

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

 

1 2 3 4 5 6 7 8 9

>>> 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)]

 

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

 

* 二維矩陣變換(矩陣的行列互換)

 

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

1 2

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

 

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

 

1 2 3 4 5

>>> 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()

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的餘數,那麼能夠寫成下面的代碼。

 

 

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

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

map-多個seq

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

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

 

 

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

 

 

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

 

 

須要注意的是,不一樣長度的多個seq是沒法執行map函數的,會出現類型錯誤。

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實現一個階乘的代碼。

 

 

那麼,若是咱們但願獲得2倍階乘的值呢?這就能夠用到init這個可選參數了。

 

幸運之神的降臨,每每只是由於你多看了一眼,多想了一下,多走了一步。
filter函數

filter()函數是 Python 內置的另外一個有用的高階函數,filter()中的兩個參數, 第一個爲func, 第二個應該是可迭代對象(字符串, 列表, 元祖, 字典, 集合, range(), 生成器)均可以,這個函數 f 的做用是對每一個元素進行判斷,返回 True或 False,filter()根據判斷結果自動過濾掉不符合條件的元素,返回由符合條件元素組成的新list。

例如,要從一個list [1, 4, 6, 7, 9, 12, 17]中刪除偶數,保留奇數,首先,要編寫一個判斷奇數的函數:

def is_odd(x):
    return x % 2 == 1

而後,利用filter()過濾掉偶數:

>>>filter(is_odd, [1, 4, 6, 7, 9, 12, 17])

結果:

[1, 7, 9, 17]

利用filter(),能夠完成不少有用的功能,例如,刪除 None 或者空字符串:

def is_not_empty(s):
    return s and len(s.strip()) > 0
>>>filter(is_not_empty, ['test', None, '', 'str', '  ', 'END'])

結果:

['test', 'str', 'END']

注意: s.strip(rm) 刪除 s 字符串中開頭、結尾處的 rm 序列的字符。

當rm爲空時,默認刪除空白符(包括'\n', '\r', '\t', ' '),以下:

>>> a = ' 123'
>>> a.strip()
'123'

>>> a = '\t\t123\r\n'
>>> a.strip()
'123'

練習:

請利用filter()過濾出1~100中平方根是整數的數,即結果應該是:

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

方法:

import math
def is_sqr(x):
    return math.sqrt(x) % 1 == 0
print filter(is_sqr, range(1, 101))

結果:

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
相關文章
相關標籤/搜索