1. 程式人生 > >Python中的lambda、map、filter、reduce、zip

Python中的lambda、map、filter、reduce、zip

sum http seq 是你 解包 range 匿名函數 三元 param

lambda

lambda是匿名函數,也就是沒有名字的函數。lambda的語法非常簡單:

技術分享

下面是一個lambda表達式的簡單例子:

註意:我們可以把lambda表達式賦值給一個變量,然後通過這個變量來使用它。

>>> my_sum = lambda x, y: x+y
>>> my_sum(1, 2)
3

下圖是定義lambda表達式和定義一個普通函數的對比:

註意:

使用lambda表達式並不能提高代碼的運行效率,它只能讓你的代碼看起來簡潔一些。

map

map()接收兩個參數func(函數)和seq(序列,例如list)。如下圖:

技術分享

技術分享

map()

將函數func應用於序列seq中的所有元素。在Python3之前,map()返回一個列表,列表中的每個元素都是將列表或元組“seq”中的相應元素傳入函數func返回的結果。Python 3中map()返回一個叠代器

因為map()需要一個函數作為參數,所以可以搭配lambda表達式很方便的實現各種需求:

  • 例子1–將一個列表裏面的每個數字都加100:
>>> l = [11, 22, 33, 44, 55]
>>> list(map(lambda x:x+100, l))
[111, 122, 133, 144, 155]
  • 例子2–

使用map就相當於使用了一個for循環,我們完全可以自己定義一個my_map

函數:

def my_map(func, seq):
    result = []
    for i in seq:
        result.append(func(i))
    return result

測試一下我們自己的my_map函數:

>>> def my_map(func, seq):
...     result = []
...     for i in seq:
...         result.append(func(i))
...     return result
... 
>>> l = [11, 22, 33, 44, 55]
>>> list(my_map(lambda x:x+100, l))
[111, 122, 133, 144, 155]

我們自定義的my_map函數的效果和內置的map函數一樣。

當然在Python3中,map函數返回的是一個叠代器,所以我們也需要讓我們的my_map函數返回一個叠代器:

def my_map(func, seq):
    for i in seq:
        yield func(i)

測試一下:

>>> def my_map(func, seq):
...     for i in seq:
...         yield func(i)
... 
>>> l = [11, 22, 33, 44, 55]
>>> list(my_map(lambda x:x+100, l))
[111, 122, 133, 144, 155]

與我們自己定義的my_map函數相比,由於map是內置的因此它始終可用,並且始終以相同的方式工作。它也具有一些性能優勢,通常會比手動編寫的for循環更快。當然內置的map還有一些高級用法:

例如,可以給map函數傳入多個序列參數,它將並行的序列作為不同參數傳入函數:

pow(arg1, arg2)函數舉例,

>>> pow(2, 10)
1024
>>> pow(3, 11)
177147
>>> pow(4, 12)
16777216
>>> list(map(pow, [2, 3, 4], [10, 11, 12]))
[1024, 177147, 16777216]

pow(arg1, arg2)函數接收兩個參數arg1和arg2,map(pow, [2, 3, 4], [10, 11, 12])就會並行從[2, 3, 4]和[10, 11, 12]中取出元素,傳入到pow中。

還有一個例子:

>>> from operator import add
>>> x = [1, 2, 3]
>>> y = [4, 5, 6]
>>> list(map(add, x, y))
[5, 7, 9]

調用map函數類似於列表推導式,但是列表推導式是對每個元素做表達式運算,而map對每個元素都會應用一次函數調用。也只有在map中使用內置函數時,才可能比列表推導式速度更快。

filter

filter函數和map函數一樣也是接收兩個參數func(函數)和seq(序列,如list),如下圖:

技術分享

filter函數類似實現了一個過濾功能,它過濾序列中的所有元素,返回那些傳入func後返回True的元素。也就是說filter函數的第一個參數func必須返回一個布爾值,即True或者False。

下面這個例子,是使用filter從一個列表中過濾出大於33的數:

>>> l = [30, 11, 77, 8, 25, 65, 4]
>>> list(filter(lambda x: x>33, l))
[77, 65]

利用filter()還可以用來判斷兩個列表的交集:

>>> x = [1, 2, 3, 5, 6]
>>> y = [2, 3, 4, 6, 7]
>>> list(filter(lambda a: a in y, x))
[2, 3, 6]

reduce

註意:Python3中reduce移到了functools模塊中,你可以用過from functools import reduce來使用它。

reduce同樣是接收兩個參數:func(函數)和seq(序列,如list),如下圖:

技術分享

reduce最後返回的不是一個叠代器,它返回一個值。

reduce首先將序列中的前兩個元素,傳入func中,再將得到的結果和第三個元素一起傳入func,…,這樣一直計算到最後,得到一個值,把它作為reduce的結果返回。

原理類似於下圖:

技術分享

看一下運行結果:

>>> from functools import reduce
>>> reduce(lambda x,y:x+y, [1, 2, 3, 4])
10

再來練習一下,使用reduce求1~100的和:

>>> from functools import reduce
>>> reduce(lambda x,y:x+y, range(1, 101))
5050

三元運算

三元運算(三目運算)在Python中也叫條件表達式。三元運算的語法非常簡單,主要是基於True/False的判斷。如下圖:

技術分享

使用它就可以用簡單的一行快速判斷,而不再需要使用復雜的多行if語句。 大多數時候情況下使用三元運算能夠讓你的代碼更清晰。

三元運算配合lambda表達式reduce,求列表裏面值最大的元素:

>>> from functools import reduce
>>> l = [30, 11, 77, 8, 25, 65, 4]
>>> reduce(lambda x,y: x if x > y else y, l)
77

再來一個,三元運算配合lambda表達式map的例子:

將一個列表裏面的奇數加100:

>>> l = [30, 11, 77, 8, 25, 65, 4]
>>> list(map(lambda x: x+100 if x%2 else x, l))
[30, 111, 177, 8, 125, 165, 4]

zip

zip函數接收一個或多個可叠代對象作為參數,最後返回一個叠代器:

>>> x = ["a", "b", "c"]
>>> y = [1, 2, 3]
>>> a = list(zip(x, y))  # 合包
>>> a
[(‘a‘, 1), (‘b‘, 2), (‘c‘, 3)]
>>> b =list(zip(*a))  # 解包
>>> b
[(‘a‘, ‘b‘, ‘c‘), (1, 2, 3)]

zip(x, y) 會生成一個可返回元組 (m, n) 的叠代器,其中m來自x,n來自y。 一旦其中某個序列叠代結束,叠代就宣告結束。 因此叠代長度跟參數中最短的那個序列長度一致。

>>> x = [1, 3, 5, 7, 9]
>>> y = [2, 4, 6, 8]
>>> for m, n in zip(x, y):
...   print(m, n)
... 
1 2
3 4
5 6
7 8

如果上面不是你想要的效果,那麽你還可以使用 itertools.zip_longest() 函數來代替這個例子中的zip

>>> from itertools import zip_longest
>>> x = [1, 3, 5, 7, 9]
>>> y = [2, 4, 6, 8]
>>> for m, n in zip_longest(x, y):
...   print(m, n)
... 
1 2
3 4
5 6
7 8
9 None

zip其他常見應用:

>>> keys = ["name", "age", "salary"]
>>> values = ["Andy", 18, 50]
>>> d = dict(zip(keys, values))
>>> d
{‘name‘: ‘Andy‘, ‘age‘: 18, ‘salary‘: 50}

Python中的lambda、map、filter、reduce、zip