三個函數比較類似,都是應用于序列的内置函數。常見的序列包括list、tuple、str
map函數
map函數會根據提供的函數對指定序列做映射。
map函數的定義:
map(function, sequence[, sequence, ...]) -> list
map()函數接收兩個參數,一個是函數,一個是序列,map将傳入的函數依次作用到序列的每個元素,并把結果作為新的list傳回。
1、當seq隻有一個時,将函數func作用于這個seq的每個元素上,并得到一個新的seq。
讓我們來看一下隻有一個seq的時候,map()函數是如何工作的。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiQ3chVEa0V3bT9CX5RXa2Fmcn9CXwczLcVmds92czlGZvwVP9EUTDZ0aRJkSwk0LcxGbpZ2LcBDM08CXlpXazRnbvZ2LcRlMMVDT2EWNvwFdu9mZvwVP9cmYwhmbiBHctJGaS1mYoxWbhZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jM2MjM1cTM2EDNxcDM3EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
示例一
比如要對一個序列中的每個元素進行平方運算:
傳回結果為:
[, , , , ]
或者
>>> def f(x):
... return x * x
...
>>> map(f, [, , , , ])
[, , , , ]
map()傳入的第一個參數是f,即函數對象本身。
注意:map()函數不改變原有的 list,而是傳回一個新的 list。
不需要map()函數,寫一個循環,也可以計算出結果
L = []
for n in [, , , , ]:
L.append(f(n))
print L
把f(x)作用在list的每一個元素并把結果生成一個新的list。
示例二
#使用lambda
>>> print map(lambda x: x % , range())
[, , , , , , ]
#使用清單解析
>>> print [x % for x in range()]
[, , , , , , ]
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])
傳回結果為:
[(, ), (, ), (, ), (, ), (, )]
map()作為高階函數,事實上它把運算規則抽象了,是以,我們不但可以計算簡單的f(x)=x2,還可以計算任意複雜的函數,比如,把這個list所有數字轉為字元串:
>>> map(str, [, , , , , , , , ])
['1', '2', '3', '4', '5', '6', '7', '8', '9']
由于list包含的元素可以是任何類型,是以,map() 不僅僅可以處理隻包含數值的 list,事實上它可以處理包含任意類型的 list,隻要傳入的函數f可以處理這種資料類型。
比如假設使用者輸入的英文名字不規範,沒有按照首字母大寫,後續字母小寫的規則,請利用map()函數,把一個list(包含若幹不規範的英文名字)變成一個包含規範英文名字的list:
輸入:[‘adam’, ‘LISA’, ‘barT’]
輸出:[‘Adam’, ‘Lisa’, ‘Bart’]
def format_name(s):
s1=s[:].upper()+s[:].lower();
return s1;
print map(format_name, ['adam', 'LISA', 'barT'])
***将元組轉換成list***
>>> map(int, (,,))
[, , ]
***将字元串轉換成list***
>>> map(int, '1234')
[, , , ]
***提取字典的key,并将結果存放在一個list中***
>>> map(int, {:,:,:})
[, , ]
***字元串轉換成元組,并将結果以清單的形式傳回***
>>> map(tuple, 'agdf')
[('a',), ('g',), ('d',), ('f',)]
#将小寫轉成大寫
def u_to_l (s):
return s.upper()
print map(u_to_l,'asdfd')
zip函數
Python函數式程式設計之zip()
zip()函數具體的工作機制是,将每個清單中同一位置的元素取出來組成一個元組,存放到一個清單中,然後傳回這個清單。
>>> x = [,,]
>>> y = ['a','b','c']
>>> z = [,,]
>>> zip_xyz = zip(x, y, z)
>>> print zip_xyz
[(, 'a', ), (, 'b', ), (, 'c', )]
對于長度不同的seq,zip()函數又怎麼處理呢?
>>> a = [,,]
>>> b = [,,,]
>>> zip_ab = zip(a, b)
>>> print zip_ab
[(, ), (, ), (, )]
從上面的例子可以看出,當seq的長度不一緻時,zip()會以最短的那個seq為主,進行處理,然後将多餘的舍棄掉。
zip()對隻有一個seq的處理:
>>> c = ['a', 'b', 'c']
>>> zip_c = zip(c)
>>> print zip_c
[('a',), ('b',), ('c',)]
unzip
>>> a = [, , ]
>>> b = ['a', 'b', 'c']
>>> zip_ab = zip(a,b)
>>> un_zip = zip(*zip_ab)
>>> print un_zip
[(, , ), ('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 = [,'a','b']
>>> zip_rx = zip(* [x] * )
>>> print zip_rx
[(, , ), ('a', 'a', 'a'), ('b', 'b', 'b')]
首先 [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(function or None, sequence) -> list, tuple, or string
filter函數會對序列參數sequence中的每個元素調用function函數,最後傳回的結果包含調用結果為True的元素序列。傳回值的類型和參數sequence的類型相同. func函數是一個布爾函數,filter()函數調用這個函數一次作用于seq中的每一個元素,篩選出符合條件的元素,并以清單的形式傳回。
示例一
比如傳回序列中的所有偶數:
def is_even(x):
return x & !=
filter(is_even, [, , , , , , , , , ])
傳回結果為:
[1, 3, 5, 7, 9]
如果function參數為None,傳回結果和sequence參數相同。
示例二
假如有個清單,清單中有幾個數字,現在我想從這些數字中,選出即能被2整除又能被3整除的數。
nums = [,,,,,]
def nums_res (x):
return x % == and x % ==
print filter(nums_res, nums)
執行結果:[, , ]
如果使用普通方法的話,就需要使用for循環去挨個挨個周遊list中的元素。當然我們也可以使用清單解析法:
>>> print [x for x in nums if x % == and x % == ]
[, , ]
reduce函數
reduce函數,即為化簡函數,reduce函數會對參數序列中元素進行累積。
reduce函數的定義:
reduce(function, sequence[, initial]) -> value
function參數是一個有兩個參數的函數,reduce依次從sequence中取一個元素,和上一次調用function的結果做參數再次調用function。
第一次調用function時,如果提供initial參數,會以sequence中的第一個元素和initial作為參數調用function,否則會以序列sequence中的前兩個元素做參數調用function。
reduce()函數的執行過程如下圖所示
reduce把一個函數作用在一個序列[x1, x2, x3…]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:
示例一
比方說對一個序列求和,就可以用reduce實作
>>> def add(x, y):
... return x + y
...
>>> reduce(add, [, , , , ])
或者
結果為25
或者
結果為25( ((((1+3)+5)+7)+9) )
當然求和運算可以直接用Python内建函數sum(),沒必要動用reduce。
示例二
從reduce函數的執行過程,很容易聯想到求一個數的階乘,而python中并沒有給出一個求階乘的内置函數,正好就拿這個例子來說明reduce函數。
#未指定init的情況
>>> n =
>>> print reduce(lambda x, y: x * y, range(, n))
上面的例子中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(, n),)
這個時候,就會将init作為第一個元素,和seq1中的第一個元素1一起傳入lambda函數中去執行,傳回結果再作為下一次的第一個元素。
但是如果要把序列[1, 3, 5, 7, 9]變換成整數13579,reduce就可以派上用場
>>> def fn(x, y):
... return x * + y
...
>>> reduce(fn, [, , , , ])
這個例子本身沒多大用處,但是,如果考慮到字元串str也是一個序列,對上面的例子稍加改動,配合map(),我們就可以寫出把str轉換為int的函數:
>>> def fn(x, y):
... return x * + y
...
>>> def char2num(s):
... return {'0': , '1': , '2': , '3': , '4': , '5': , '6': , '7': , '8': , '9': }[s]
...
>>> reduce(fn, map(char2num, '13579'))
整理成一個str2int的函數就是:
def str2int(s):
def fn(x, y):
return x * + y
def char2num(s):
return {'0': , '1': , '2': , '3': , '4': , '5': , '6': , '7': , '8': , '9': }[s]
return reduce(fn, map(char2num, s))
還可以用lambda函數進一步簡化成
def char2num(s):
return {'0': , '1': , '2': , '3': , '4': , '5': , '6': , '7': , '8': , '9': }[s]
def str2int(s):
return reduce(lambda x,y: x*+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
、單個參數的:
>>> g = lambda x : x **
>>> print g()
、多個參數的:
>>> g = lambda x, y, z : (x + y) ** z
>>> print g(,,)
lambda表達式會傳回一個函數對象,如果沒有變量接受這個傳回值的話,它很快就會被丢棄。也正是由于lambda隻是一個表達式,是以它可以直接作為list和dict的成員。如:
>>> list_a = [lambda a: a**, lambda b: b**]
>>> list_a[]
<function <lambda> at >
>>> g = list_a[]
>>> g()
lambda表達式中,冒号前面是參數,可以有多個,用逗号分隔,冒号右邊是傳回值。
參考文獻
python中的map、filter、reduce函數
python map函數
Python map()函數的用法
Python reduce()函數的用法
Python filter()函數的用法
Python lambda函數的用法