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