Python高阶函数--map、lambda、reduce、filter、zip
一、map()函數(shù)
map()是 Python 內(nèi)置的高階函數(shù),它接收一個(gè)函數(shù) f 和一個(gè) list,并通過(guò)把list 的每個(gè)元素依次作用在函數(shù) f 上,得到一個(gè)新的 list 并返回。 例如,對(duì)于list [1, 2, 3, 4, 5, 6, 7, 8, 9] 如果希望把list的每個(gè)元素都作平方,就可以用map()函數(shù),我們只需要傳入函數(shù)f(x)=x*x,就可以利用map()函數(shù)完成這個(gè)計(jì)算:
def f(x):return x*x print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])輸出結(jié)果: [1, 4, 9, 10, 25, 36, 49, 64, 81]注意:map()函數(shù)不改變?cè)械?list,而是返回一個(gè)新的 list。 利用map()函數(shù),可以把一個(gè) list 轉(zhuǎn)換為另一個(gè) list,只需要傳入轉(zhuǎn)換函數(shù)。 由于list包含的元素可以是任何類(lèi)型,因此,map() 不僅僅可以處理只包含數(shù)值的 list,事實(shí)上它可以處理包含任意類(lèi)型的 list,只要傳入的函數(shù)f可以處理這種數(shù)據(jù)類(lèi)型。
任務(wù) 假設(shè)用戶(hù)輸入的英文名字不規(guī)范,沒(méi)有按照首字母大寫(xiě),后續(xù)字母小寫(xiě)的規(guī)則,請(qǐng)利用map()函數(shù),把一個(gè)list(包含若干不規(guī)范的英文名字)變成一個(gè)包含規(guī)范英文名字的list: 輸入:['adam', 'LISA', 'barT'] 輸出:['Adam', 'Lisa', 'Bart']
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' def format_name(s):s1=s[0:1].upper()+s[1:].lower();return s1;print map(format_name, ['adam', 'LISA', 'barT'])map()函數(shù)是python內(nèi)置的高階函數(shù),對(duì)傳入的list的每一個(gè)元素進(jìn)行映射,返回一個(gè)新的映射之后的list
python3中,map函數(shù)返回的是一個(gè)map對(duì)象,需要list(map(fun,itor))來(lái)將映射之后的map對(duì)象轉(zhuǎn)換成列表
二、lambda 函數(shù)
python 使用 lambda 來(lái)創(chuàng)建匿名函數(shù)。
- lambda只是一個(gè)表達(dá)式,函數(shù)體比def簡(jiǎn)單很多。
- lambda的主體是一個(gè)表達(dá)式,而不是一個(gè)代碼塊。僅僅能在lambda表達(dá)式中封裝有限的邏輯進(jìn)去。
- lambda函數(shù)擁有自己的命名空間,且不能訪問(wèn)自有參數(shù)列表之外或全局命名空間里的參數(shù)。
- 雖然lambda函數(shù)看起來(lái)只能寫(xiě)一行,卻不等同于C或C++的內(nèi)聯(lián)函數(shù),后者的目的是調(diào)用小函數(shù)時(shí)不占用棧內(nèi)存從而增加運(yùn)行效率。
語(yǔ)法
lambda函數(shù)的語(yǔ)法只包含一個(gè)語(yǔ)句,如下:
lambda [arg1 [,arg2,.....argn]]:expression以lambda x: x+1為例,首先,它是一個(gè)函數(shù):
def f(x): return x+1好,這個(gè)函數(shù)引用時(shí)需要傳入一個(gè)參數(shù),并且有一個(gè)返回值。這個(gè)參數(shù)一般是for x in L之類(lèi)的傳進(jìn)來(lái),或者直接調(diào)用f(3)。
(1)先看第一個(gè)例子
f = lambda x: x**2 print(f(5)) # 25結(jié)果是25,很easy,這里要說(shuō)明的是lambda x: x**2是一個(gè)函數(shù),你如果print(f)的得到的是一個(gè)函數(shù)的地址,記住它是一個(gè)函數(shù)。
(2)和append搭配、在for循環(huán)內(nèi)部
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' for x in range(5):li.append(lambda x: x**2) print(li[0](2)) # 4 print(li[1](3)) # 9注:此處省略li = []的初始化代碼,后續(xù)一樣
li是一個(gè)list,但是list里面存的可不是數(shù),而是函數(shù)地址,而且是5個(gè)x**2的函數(shù),所以無(wú)論你是li[0](2)還是li[1](2),結(jié)果都是4。一般情況下不會(huì)這樣寫(xiě)程序,因?yàn)闆](méi)什么用途。
這里說(shuō)一下,看過(guò)一個(gè)程序這樣寫(xiě),猜測(cè)原作者是想讓li在運(yùn)算時(shí)append的是數(shù)據(jù),或者是以為這樣可以讓li在調(diào)用時(shí)n的值不隨x變,不管這樣,這個(gè)程序?qū)嶋H效果和上面一樣,x本身在變,n = x寫(xiě)不寫(xiě)沒(méi)有區(qū)別,li內(nèi)部仍然是5個(gè)一樣的函數(shù)的地址。
for x in range(5):li.append(lambda n=x: n**2) print(li[0](2)) # 4 print(li[1](3)) # 9總結(jié)一下:lambda在for循環(huán)內(nèi)部,和append搭配時(shí),for循環(huán)不是為了給函數(shù)傳遞參數(shù),只是為了生成多個(gè)函數(shù)。
(3)只和append搭配
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' li.append(lambda x: x**2) print(li[0](1)) # 1 print(li[0](3)) # 9 print(li[1](3)) # IndexError: list index out of range這兒說(shuō)的是另外一種情況,程序中并沒(méi)有給出匿名函數(shù)lambda的參數(shù),在調(diào)用時(shí)才會(huì)給。而且li僅僅append了一次,所以li內(nèi)部也僅有一個(gè)函數(shù)地址。調(diào)用時(shí)就不會(huì)有l(wèi)i[1]這種情況。
補(bǔ)充一種它的變形,說(shuō)明一下對(duì)于這種情況,參數(shù)賦初值并無(wú)意義。
li.append(lambda x=5: x**2) print(li[0](1)) # 1 print(li[0](3)) # 9 print(li[1](3)) # IndexError: list index out of range(4)和append搭配、參數(shù)由for循環(huán)給出
舉個(gè)栗子
li.append(lambda :x for x in range(10)) print(next(li[0])()) # 0 print(next(li[0])()) # 1 print(next(li[1])()) # IndexError: list index out of range此處有大坑,首先你得認(rèn)出來(lái)(lambda :x for x in range(10))這種形式可沒(méi)有那么簡(jiǎn)單,這是產(chǎn)生一個(gè)生成器最簡(jiǎn)單的方法,它的返回值是一個(gè)generator,所以li內(nèi)部就存了一個(gè)generator。還有此時(shí)的函數(shù)是沒(méi)有參數(shù)的,等效為:
def f(): return x有人會(huì)說(shuō)這個(gè)函數(shù)有什么意義嗎,是沒(méi)什么意義,但是如果return x**2,其實(shí)還是有些意義的。
(5)放在[]中、參數(shù)由for循環(huán)給出
li = [lambda :x for x in range(10)] print(li[0]()) # 9 print(li[1]()) # 9這個(gè)函數(shù)其實(shí)不好理解,首先別看成生成器了,跟它沒(méi)關(guān)系。
lambda :x仍然是一個(gè)函數(shù)(return x),在沒(méi)有print(li[0]())之前它是不會(huì)被執(zhí)行的,一旦運(yùn)行print(li[0]()),就會(huì)輸出x的值,那么x是多少呢,顯然x在上一句程序里面已經(jīng)變成9了,所以結(jié)果都是9,這里其實(shí)是閉包的問(wèn)題,想避免這個(gè)問(wèn)題,程序就不能寫(xiě)這么簡(jiǎn)潔了。
結(jié)果是0, 1, 4, 9, 16,是我們想要的,有人會(huì)說(shuō)這兒為什么不把def f()簡(jiǎn)化一下呢?還真不能簡(jiǎn)化,比較結(jié)果便知:
for x in range(5): li.append(lambda :x**2) # uninstant run print(li[0](), li[1](), li[2](), li[3](), li[4]()) #16 16 16 16 16看到區(qū)別了吧,f 是一個(gè)函數(shù)地址,而 f() 是一個(gè)函數(shù)被執(zhí)行后的返回值,所以第一個(gè)程序可以得到每次循環(huán)的 x 值。
(6)lambda最常用:和map、reduce、filter等結(jié)合用
其實(shí)lambda最常用的還是和map、reduce、filter這些高級(jí)函數(shù)結(jié)合使用,不過(guò)那個(gè)時(shí)候就把它當(dāng)做一個(gè)函數(shù),而且格式相對(duì)固定,具體使用就看高級(jí)函數(shù)的使用規(guī)則,較為簡(jiǎn)單,就不展開(kāi)。
#我們?cè)瓉?lái)的函數(shù)是這樣的 def square_z(x):return xx #現(xiàn)在我們可以寫(xiě)成下面這樣(冒號(hào)后面的一切都是對(duì)輸入的操作,然后lambda x會(huì)返回結(jié)果):square1=lambda x:xx print(square1(2)) #配合map,filter等lambda能發(fā)揮更大作用,一行代碼就能打印列表內(nèi)元素的平方數(shù) print(list(map(lambda x:x*x,[1,2,3,4,5]))) print(list(filter(lambda x:x<3,[1,2,3,4,5])))三、歸納函數(shù)(reduce):
第一個(gè)參數(shù)是函數(shù)名,第二個(gè)參數(shù)是sequence(序列,像list,tuple,str,set,dict都可以)
效果是這樣的:reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' #提前準(zhǔn)備一個(gè)函數(shù),計(jì)算兩數(shù)之和 from functools import reduce def add_z(x,y): return x+y #計(jì)算1~10之間數(shù)字之和(還是不包含10) r_z=reduce(add_z,range(1,10)) print(r_z) print("r_z 的類(lèi)型:%s"%type(r_z))結(jié)果如下:
四、過(guò)濾器(filter):
第一個(gè)參數(shù)是函數(shù)名,用于篩選的函數(shù),第二個(gè)參數(shù)是Iterable(list,tuple,set,dict,str),返回一個(gè)filter且filter屬于Iterator
#用于過(guò)濾掉一切不需要的東西,下面我們以打印1~10之間的奇數(shù)為例說(shuō)明: from collections import Iterable,Iterator #提前準(zhǔn)備一個(gè)函數(shù),判斷是否為奇數(shù) def odd_z(x):if x%2==1:return Trueelse:return False f=filter(odd_z,range(1,10)) print("f 的類(lèi)型:%s"%type(f)) print("f 是Iterator:%s"%isinstance(f,Iterator)) try:print(next(f),end='*')#f作為Iterator使用print(next(f),end='*') except:print("\n結(jié)束了") for i in f:#f作為Iterable使用print(i,end='$')結(jié)果如下:
五、zip函數(shù)
zip() 函數(shù)用于將可迭代對(duì)象作為參數(shù),將對(duì)象中對(duì)應(yīng)的元素打包成一個(gè)個(gè)元組,然后返回由這些元組組成的對(duì)象。
如果各個(gè)可迭代對(duì)象的元素個(gè)數(shù)不一致,則返回的對(duì)象長(zhǎng)度與最短的可迭代對(duì)象相同。
利用 * 號(hào)操作符,與zip相反,進(jìn)行解壓。
語(yǔ)法:
zip(iterable1,iterable2, ...)參數(shù)說(shuō)明:
iterable–一個(gè)或多個(gè)可迭代對(duì)象(字符串,列表,元組,字典)
舉例說(shuō)明
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' a = [1, 2, 3] b = [4, 5, 6] c = [7, 8, 9] z = zip(a, b, c)print('z值:', list(z))print('打包a、c列表:', list(zip(a, c)))z = zip(a, b) print('解壓z:', list(zip(*z)))# 字典形式 v1 = {1: 11, 2: 22} v2 = {3: 33, 4: 44} v3 = {5: 55, 6: 66} v = zip(v1, v2, v3) print('v值:', list(v)) w = zip(*zip(v1, v2, v3)) print("w值:", list(w))# 搭配for循環(huán) list1 = [2, 3, 4] list2 = [5, 6, 7] for x, y in zip(list1, list2):print(x, y, '--', x * y)結(jié)果:
/usr/local/bin/python3.9 /Users/chenshifeng/MyCode/PythonCode/SFDSZL/1/a.py z值: [(1, 4, 7), (2, 5, 8), (3, 6, 9)] 打包a、c列表: [(1, 7), (2, 8), (3, 9)] 解壓z: [(1, 2, 3), (4, 5, 6)] v值: [(1, 3, 5), (2, 4, 6)] w值: [(1, 2), (3, 4), (5, 6)] 2 5 -- 10 3 6 -- 18 4 7 -- 28Process finished with exit code 0總結(jié)
以上是生活随笔為你收集整理的Python高阶函数--map、lambda、reduce、filter、zip的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python计算文件md5值
- 下一篇: Python教程:Sys 与 Impor