Python函数式编程-map()、zip()、filter()、reduce()、lambda()
三個函數比較類似,都是應用于序列的內置函數。常見的序列包括list、tuple、str
map函數
map函數會根據提供的函數對指定序列做映射。
map函數的定義:
map(function, sequence[, sequence, ...]) -> listmap()函數接收兩個參數,一個是函數,一個是序列,map將傳入的函數依次作用到序列的每個元素,并把結果作為新的list返回。
1、當seq只有一個時,將函數func作用于這個seq的每個元素上,并得到一個新的seq。
讓我們來看一下只有一個seq的時候,map()函數是如何工作的。
示例一
比如要對一個序列中的每個元素進行平方運算:
map(lambda x: x ** 2, [1, 2, 3, 4, 5])返回結果為:
[1, 4, 9, 16, 25]或者
>>> def f(x): ... return x * x ... >>> map(f, [1, 2, 3, 4, 5]) [1, 4, 9, 16, 25]map()傳入的第一個參數是f,即函數對象本身。
注意:map()函數不改變原有的 list,而是返回一個新的 list。
不需要map()函數,寫一個循環,也可以計算出結果
L = [] for n in [1, 2, 3, 4, 5]:L.append(f(n)) print L把f(x)作用在list的每一個元素并把結果生成一個新的list。
示例二
#使用lambda >>> print map(lambda x: x % 2, range(7)) [0, 1, 0, 1, 0, 1, 0] #使用列表解析 >>> print [x % 2 for x in range(7)] [0, 1, 0, 1, 0, 1, 0]2、當seq多于一個時,map可以并行(注意是并行)地對每個seq執行如下圖所示的過程
在參數存在多個序列時,會依次以每個序列中相同位置的元素做參數調用function函數。
示例
比如要對兩個序列中的元素依次求和。
map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])map返回的list中第一個元素為,參數序列1的第一個元素加參數序列2中的第一個元素(1 + 2),
list中的第二個元素為,參數序列1中的第二個元素加參數序列2中的第二個元素(3 + 4),
依次類推,最后的返回結果為:
要注意function函數的參數數量,要和map中提供的集合數量相匹配。
如果集合長度不相等,會以最小長度對所有集合進行截取。
當函數為None時,操作和zip相似:
map(None, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])返回結果為:
[(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]map()作為高階函數,事實上它把運算規則抽象了,因此,我們不但可以計算簡單的f(x)=x2,還可以計算任意復雜的函數,比如,把這個list所有數字轉為字符串:
>>> map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]) ['1', '2', '3', '4', '5', '6', '7', '8', '9']由于list包含的元素可以是任何類型,因此,map() 不僅僅可以處理只包含數值的 list,事實上它可以處理包含任意類型的 list,只要傳入的函數f可以處理這種數據類型。
比如假設用戶輸入的英文名字不規范,沒有按照首字母大寫,后續字母小寫的規則,請利用map()函數,把一個list(包含若干不規范的英文名字)變成一個包含規范英文名字的list:
輸入:[‘adam’, ‘LISA’, ‘barT’]
輸出:[‘Adam’, ‘Lisa’, ‘Bart’]
zip函數
Python函數式編程之zip()
zip()函數具體的工作機制是,將每個列表中同一位置的元素取出來組成一個元組,存放到一個列表中,然后返回這個列表。
對于長度不同的seq,zip()函數又怎么處理呢?
>>> a = [1,2,3] >>> b = [4,5,6,7] >>> zip_ab = zip(a, b) >>> print zip_ab [(1, 4), (2, 5), (3, 6)]從上面的例子可以看出,當seq的長度不一致時,zip()會以最短的那個seq為主,進行處理,然后將多余的舍棄掉。
zip()對只有一個seq的處理:
>>> c = ['a', 'b', 'c'] >>> zip_c = zip(c) >>> print zip_c [('a',), ('b',), ('c',)]unzip
>>> a = [1, 2, 3] >>> b = ['a', 'b', 'c'] >>> zip_ab = zip(a,b) >>> un_zip = zip(*zip_ab) >>> print un_zip [(1, 2, 3), ('a', 'b', 'c')]一般認為這是一個unzip過程,工作原理如下:
在運行zip(*zip_ab)之前,zip_ab的值是:[(1, ‘a’), (2, ‘b’), (3, ‘c’)]
而zip(*zip_ab)就等價于zip((1, ‘a’), (2, ‘b’), (3, ‘c’))
所以得出結果:[(1, 2, 3), (‘a’, ‘b’, ‘c’)]
首先 [x]生成一個列表的列表:[[1, ‘a’, ‘b’]],這個列表中只有一個元素[1,’a’,’b’]
其次[x] * 3,表示將列表中的元素打印三次,即生成了含有三個元素的列表:
[[1, ‘a’, ‘b’], [1, ‘a’, ‘b’], [1, ‘a’, ‘b’]]
最后是zip(* [x] * 3)就等價于
zip([1, ‘a’, ‘b’], [1, ‘a’, ‘b’], [1, ‘a’, ‘b’])
filter函數
filter函數會對指定序列執行過濾操作。
filter函數的定義:
filter函數會對序列參數sequence中的每個元素調用function函數,最后返回的結果包含調用結果為True的元素序列。返回值的類型和參數sequence的類型相同. func函數是一個布爾函數,filter()函數調用這個函數一次作用于seq中的每一個元素,篩選出符合條件的元素,并以列表的形式返回。
示例一
比如返回序列中的所有偶數:
def is_even(x): return x & 1 != 0filter(is_even, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])返回結果為:
[1, 3, 5, 7, 9]
如果function參數為None,返回結果和sequence參數相同。
示例二
假如有個列表,列表中有幾個數字,現在我想從這些數字中,選出即能被2整除又能被3整除的數。
nums = [2,3,6,12,15,18] def nums_res (x):return x % 2 == 0 and x % 3 == 0 print filter(nums_res, nums) 執行結果:[6, 12, 18]如果使用普通方法的話,就需要使用for循環去挨個挨個遍歷list中的元素。當然我們也可以使用列表解析法:
>>> print [x for x in nums if x % 2 == 0 and x % 3 == 0] [6, 12, 18]reduce函數
reduce函數,即為化簡函數,reduce函數會對參數序列中元素進行累積。
reduce函數的定義:
function參數是一個有兩個參數的函數,reduce依次從sequence中取一個元素,和上一次調用function的結果做參數再次調用function。
第一次調用function時,如果提供initial參數,會以sequence中的第一個元素和initial作為參數調用function,否則會以序列sequence中的前兩個元素做參數調用function。
reduce()函數的執行過程如下圖所示
reduce把一個函數作用在一個序列[x1, x2, x3…]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)示例一
比方說對一個序列求和,就可以用reduce實現
>>> def add(x, y): ... return x + y ... >>> reduce(add, [1, 3, 5, 7, 9]) 25或者
reduce(lambda x, y: x + y, [1, 3, 5, 7, 9])結果為25
或者
reduce(lambda x, y: x + y, [3, 5, 7, 9], 1)結果為25( ((((1+3)+5)+7)+9) )
當然求和運算可以直接用Python內建函數sum(),沒必要動用reduce。
示例二
從reduce函數的執行過程,很容易聯想到求一個數的階乘,而python中并沒有給出一個求階乘的內置函數,正好就拿這個例子來說明reduce函數。
#未指定init的情況 >>> n = 6 >>> print reduce(lambda x, y: x * y, range(1, n)) 120上面的例子中range(1,6)函數生成的是一個[1, 2, 3, 4, 5]這樣的列表,這里我們給它個名叫seq1吧,reduce()函數執行時,由于沒有指定init參數,所以將取seq1中的第一個元素1,作為第一個元素,由于前面的lambda有2個變量,所以需要兩個實參,于是就取seq1中的第2個元素2,與第一個元素1一起傳入lambda中去執行,并將返回結果2,并同下一個元素3再一起傳入lambda中執行,再次返回的結果,作為下一次執行的第一個元素,依次類推,就得出結果5! = 120。
如果我們希望得到階乘的結果再多增加幾倍,可以啟用init這個可選項。如:
>>> print reduce(lambda x, y: x * y, range(1, n),2) 240這個時候,就會將init作為第一個元素,和seq1中的第一個元素1一起傳入lambda函數中去執行,返回結果再作為下一次的第一個元素。
但是如果要把序列[1, 3, 5, 7, 9]變換成整數13579,reduce就可以派上用場
>>> def fn(x, y): ... return x * 10 + y ... >>> reduce(fn, [1, 3, 5, 7, 9]) 13579這個例子本身沒多大用處,但是,如果考慮到字符串str也是一個序列,對上面的例子稍加改動,配合map(),我們就可以寫出把str轉換為int的函數:
>>> def fn(x, y): ... return x * 10 + y ... >>> def char2num(s): ... return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] ... >>> reduce(fn, map(char2num, '13579')) 13579整理成一個str2int的函數就是:
def str2int(s):def fn(x, y):return x * 10 + ydef char2num(s):return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]return reduce(fn, map(char2num, s))還可以用lambda函數進一步簡化成
def char2num(s):return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] def str2int(s):return reduce(lambda x,y: x*10+y, map(char2num, s))也就是說,假設Python沒有提供int()函數,你完全可以自己寫一個把字符串轉化為整數的函數,而且只需要幾行代碼
注意function函數不能為None。
lambda函數
Python中,lambda函數也叫匿名函數,及即沒有具體名稱的函數,它允許快速定義單行函數,類似于C語言的宏,可以用在任何需要函數的地方。這區別于def定義的函數。
lambda與def的區別:
1)def創建的方法是有名稱的,而lambda沒有。
2)lambda會返回一個函數對象,但這個對象不會賦給一個標識符,而def則會把函數對象賦值給一個變量(函數名)。
3)lambda只是一個表達式,而def則是一個語句。
4)lambda表達式” : “后面,只能有一個表達式,def則可以有多個。
5)像if或for或print等語句不能用于lambda中,def可以。
6)lambda一般用來定義簡單的函數,而def可以定義復雜的函數。
6)lambda函數不能共享給別的程序調用,def可以。
lambda語法格式:
lambda 變量 : 要執行的語句
lambda [arg1 [, agr2,…..argn]] : expression
1、單個參數的: >>> g = lambda x : x ** 2 >>> print g(3) 9 2、多個參數的: >>> g = lambda x, y, z : (x + y) ** z >>> print g(1,2,2) 9lambda表達式會返回一個函數對象,如果沒有變量接受這個返回值的話,它很快就會被丟棄。也正是由于lambda只是一個表達式,所以它可以直接作為list和dict的成員。如:
>>> list_a = [lambda a: a**3, lambda b: b**3] >>> list_a[0] <function <lambda> at 0x0259B8B0> >>> g = list_a[0] >>> g(2) 8lambda表達式中,冒號前面是參數,可以有多個,用逗號分隔,冒號右邊是返回值。
參考文獻
python中的map、filter、reduce函數
python map函數
Python map()函數的用法
Python reduce()函數的用法
Python filter()函數的用法
Python lambda函數的用法
總結
以上是生活随笔為你收集整理的Python函数式编程-map()、zip()、filter()、reduce()、lambda()的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 招商银行哆啦A梦声音卡年费多少?怎么免年
- 下一篇: Python函数之 ceil, floo