什麼是高階函數:一個函數可以作為參數傳給另外一個函數(一個函數可以用來接收另一個函數作為參數),或者一個函數的返回值為另外一個函數(若返回值為該函數本身,則為遞歸),滿足其一則為高階函數。函數的形參位置必須接受一個函數對象。 代碼理解高階函數的含義: 1 '''函數當做參數被傳遞到另個函數是什麼樣的 ...
什麼是高階函數:一個函數可以作為參數傳給另外一個函數(一個函數可以用來接收另一個函數作為參數),或者一個函數的返回值為另外一個函數(若返回值為該函數本身,則為遞歸),滿足其一則為高階函數。函數的形參位置必須接受一個函數對象。
代碼理解高階函數的含義:
1 '''函數當做參數被傳遞到另個函數是什麼樣的。把abs()函數賦值給了f變數,接下來就可以像使用abs()函數本身那樣使用f變數了,區別隻是換了個名字而已''' 2 3 f = abs # 將求絕對值的abs函數賦值給f變數 4 f(-123) # f變數等同於abs函數的功能和性質,區別隻是換了個別名 5 print(f(-123)) # 輸出結果 123 6 print(type(f)) # <builtin_function_or_method> 查看下這個f變數的類型,顯示為內置函數,因為它的真身就是內置abs()函數 7
8 '''這說明變數可以指向函數,既然變數可以指向函數,而我們知道函數的參數可以接收變數。也就是說一個函數可以接收另一個函數作為參數,一起來看看下麵這個例子''' 9 def add_(a, b, f_): 10 return f_(a) + f_(b) # 在本例中等同於 abs(a) + abs(b) 11 12 result = add_(-10, -20, abs) # 這裡把python內置函數abs作為參數傳遞給add_ 13 print(result) # 30
代碼演示高階函數兩種場景:
1 # 高階函數之 ---》參數為函數 2 def bar(): 3 print("in the bar..") 4 def foo(func): 5 func() 6 print("in the foo..") 7 8 foo(bar) 9 10 11 # 高階函數之 ---》返回值為函數 12 def bar(): 13 print("in the bar..") 14 def foo(func): 15 print("in the foo..") 16 return bar 17 res=foo(bar) 18 res() 19 20 '''以上兩個示例中,函數foo()為高階函數。示例一中函數bar作為foo的參數傳入;示例二中函數bar作為foo的返回值。
註意:函數名(例如bar 、foo)-->其為該函數的記憶體地址;函數名+括弧(例如 bar()、foo() )-->調用該函數'''
python里的高階函數有 filter、map、reduce、sorted、匿名函數lambda,遞歸函數等。
1). map函數
功能:map函數接收的是兩個參數,接收一個函數 f 和一個或多個序列list,其功能是將序列中的值處理再依次返回至新列表內,其返回值為一個迭代器對象。
語法格式:map(function, iterable,[iterable1, ...iterablen]):
參數:(1).function: 函數對象 ;(2).iterable:序列(可迭代)對象 (字元串、列表、range...)
返回值:得到的這個map對象是一個迭代器對象,屬於惰性序列的範疇。
代碼演示map實現原理:
1 # 需求:將lt = ['1','2','3','4','5'] 轉換成 [1,2,3,4,5] 2 3 # 代碼實現一:使用傳統技術來實現 4 lt = ['1','2','3','4','5','6'] 5 lt1 = [] 6 for i in lt: 7 num = int(i) 8 lt1.append(num) 9 print(lt1) # [1, 2, 3, 4, 5, 6] 由於列表屬於非惰性序列範疇,即可以直接列印看效果 10 11 12 # 代碼實現二:使用新技術來實現 13 # 思路步驟一:定義一個函數,功能:將str數據 --> int數據 14 import collections 15 lt = ['1','2','3','4','5','6']
16 def chr2Int(chr): 17 return int(chr) 18 19 mo = map(chr2Int,lt) # 這裡的chr2Int後面不能加(),也不能傳參***** 20 print(map,type(mo)) # <class 'map'> <class 'map'> 21 print(isinstance(mo,collections.Iterator)) # True,驗證是否是迭代器對象,True才能使用next 22 print(next(mo)) # 1 23 print(list(mo)) # [2, 3, 4, 5, 6] 將map對象(惰性的)轉換為list對象(非惰性的) 24 25 26 #代碼實現三:終極操作 27 print(list(map(chr2Int,lt))) #[1, 2, 3, 4, 5, 6] 28 print(list(map(int,lt)) #[1, 2, 3, 4, 5, 6] 29 30 '''map(int,lt):執行過程如下: 31 1).lt --> 取出第一個元素:'1'當做實際參數傳遞給int函數的形參位置 --> int('1'),將轉換以後的結果:1保留到map對象的第一個元素位置 32 2).lt --> 取出第二個元素:'2'當做實際參數傳遞給int函數的形參位置 --> int('2'),將轉換以後的結果:2保留到map對象的第二個元素位置 33 以此類推... 34 直到map函數執行完了,整個map對象才真正成型了...'''
代碼演示示例:
1 # 實例1: lt = [1,2,3,4,5] --> 得到:['1','2','3','4','5'] 2 3 lt = [1,2,3,4,5] 4 5 # 自定義函數:從int --》 str 6 def int2Str(i): 7 return str(i) 8 9 print(list(map(int2Str,lt))) # ['1', '2', '3', '4', '5'] 10 print(list(map(str,lt))) # ['1', '2', '3', '4', '5'] 11 print(list(map(lambda x: str(x),lt))) # ['1', '2', '3', '4', '5'] 12 13 14 # 實例2:lt = [1,2,3,4,5] --> 得到:[1,4,9,16,25] 15 16 lt = [1,2,3,4,5] 17 18 # 自定義函數:目標實現開方操作 19 def kaifang(num): 20 return num ** 2 21 22 print(list(map(kaifang,lt))) # [1, 4, 9, 16, 25] 23 print(list(map(lambda x: x ** 2,lt))) # [1, 4, 9, 16, 25],map結合匿名函數使用,用的比較多
2).reduce函數
功能:reduce函數也是一個參數為函數,一個為可迭代(序列)對象的高階函數,但reduce()傳入的函數必須接收兩個參數,reduce()對list的每個元素反覆調用函數function。所以reduce()函數接收的參數和 map()類似,但是行為不同。reduce() 函數會對參數序列中元素進行累積,其返回值為一個值而不是迭代器對象,故其常用與疊加、疊乘等。
語法格式:reduce(function, iterable[, iterable1,...,iterablen] [, initializer])
參數:function -- 函數,有兩個參數。iterable -- 可迭代對象。initializer -- 可選,初始參數
返回值:為一個值,而不是迭代器對象
【註意】:reduce函數屬於functools模塊中的函數,所以需要顯示的先導入functools模塊再使用from functools import reduce
代碼演示reduce實現原理:
1 from functools import reduce 2 3 '''當調用reduce(f,[1,3,5,7,9])時,reduce函數將做如下計算:由於f這個函數的功能是計算兩個元素的值,所以先計算頭兩個元素:f(1,3), 4 結果為4;再把結果和第3個元素計算:f(4,5),結果為9;再把結果和第4個元素計算:f(9,7),結果為16; 5 再把結果和第5個元素計算:f(16,9),結果為25;由於沒有更多的元素了,計算結束,返回結果25。''' 6 def f(x, y): 7 return x + y 8 9 result = reduce(f, [1, 3, 5, 7, 9]) 10 print(result) # 25 11 12 13 '''reduce()**還可以接收第3個可選參數,作為計算的初始值。如果把初始值設為100,如計算:結果將變為125,
因為第一輪計算是:計算初始值和第一個元素:f(100, 1),結果為101。''' 14 reduce(f, [1, 3, 5, 7, 9], 100) 15 16 17 # 使用 lambda 匿名函數 18 reduce(lambda x, y: x+y, [1,3,5,7,9])
1 '''reduce函數執行順序:先將lsd中的第一和第二個元素傳入到fn中參與運算,運算後得到結果,再和第三個元素傳入到fn中參與運算,以此類推...''' 2 3 # 需求:得到元祖tp = (1,2,3,4)中元素的和值 4 5 '''首先自定義函數 --> add作用:對列表中的元素進行求和操作 def add(x,y) 6 然後使用reduce函數執行過程如下: 7 第一次:add(1,2) 8 第二次:add(add(1,2),3) 9 第三次:add(add(add(1,2),3),4)''' 10 11 # 代碼實現一:遞歸的思想來實現 12 tp = (1,2,3,4) 13 def mySum(num): 14 if num == 1: 15 return 1 16 return num + mySum(num - 1) 17 18 print(mySum(4)) 19 20 21 # 代碼實現二:reduce函數實現 22 from functools import reduce 23 def add(x,y): 24 return x + y 25 26 res = reduce(add,tp) 27 28 print(res,type(res)) # 10 <class 'int'> 29 print(reduce(lambda x,y: x + y,tp)) # 10 30 print(sum(tp)) # 10 直接使用內置函數sum()了
代碼演示示例:
1 # 實例1:lt = [1,2,3,4] 得到其中元素的乘積 2 3 lt = [1,2,3,4] 4 print(reduce(lambda x,y: x * y,lt)) 5 6 # 實例2:從鍵盤讀入一個整數字元串數據,例如:'12345',將其轉換為12345; 7 '''註意:不能直接使用int()來實現.思路:使用map和reduce配合來實現 8 步驟一:'12345' --》拆分為散裝數據:1 2 3 4 5 可以使用map來實現 9 步驟二:將map對象中的數據 1 2 3 4 5 組合成為 --> 12345 可以使用reduce來實現 10 ''' 11 from functools import reduce 12 13 str1 = '12345' 14 def chr2Int(str): 15 return int(str) 16 17 def zuhe(x,y): 18 return x * 10 + y 19 20 mo = map(chr2Int,str1) 21 num = reduce(zuhe,mo) 22 print(num,type(num)) #12345 <class 'int'> 23 24 25 #終極版: 26 print(reduce(lambda x,y: x * 10 + y,map(int,str1))) #12345
3).filter函數
功能:filter()函數也是接收兩個參數,接收一個函數和一個序列的高階函數,其主要功能是過濾,過濾掉不符合條件的元素,序列的每個元素作為參數傳遞給函數進行判,然後返回 True 或 False,最後將返回 True 的元素放到新序列中。filter的意思:在電腦領域中我們都稱為過濾器。
語法格式:filter(function, iterable)
參數:和map、reduce一樣理解,function:判斷函數,iterable :可迭代對象。
返回值:一個惰性序列對象(filter對象,迭代器對象),例如列表
代碼演示示例:
1 # 示例1:lt = [1,2,3,4,5,6,7,8] --> 得到:[2,4,6,8] 2 3 lt = [1,2,3,4,5,6,7,8] 4 #代碼實現一:老技術 5 lt1 = [] 6 for i in lt: 7 if i % 2 == 0: 8 lt1.append(i) 9 10 print(lt1) 11 12 13 #代碼實現二:新技術(filter) 14 def func(o): 15 if o % 2 == 0: 16 return True 17 return False 18 19 fo =filter(func,lt) 20 21 print(fo,type(fo)) #<filter object at 0x0000000001E8F710> <class 'filter'> 22 print(list(filter(func,lt))) #[2, 4, 6, 8] 23 print(isinstance(fo,collections.Iterator)) #Ture 24 print(isinstance(fo,collections.Iterable)) #Ture 25 print(next(fo)) #2 26 print(next(fo)) #4 27 print(list(fo)) #[6, 8] 28 29 30 # 終極版: 31 print(list(filter(lambda x:x % 2 == 0,lt))) #[2, 4, 6, 8] 32 33 34 # 示例2:lt = [345,0,'abcde',1.2,0,3.14,0.0,'haha','hehe',True,False,[],(),{},{1,2,3},[10,20,30],{'name':'zs','age':30},None] 35 得到如下效果:lt = [345,'abcde',1.2,3.14,'haha','hehe',True,{1,2,3},[10,20,30],{'name':'zs','age':30}] 36 37 lt = [345,0,'abcde',1.2,0,3.14,0.0,'haha','hehe',True,False,[] 38 ,(),{},{1,2,3},[10,20,30],{'name':'zs','age':30},None] 39 40 print(list(filter(lambda x: bool(x),lt))) 41 #或者 42 print(list(filter(bool,lt))) 43 44 45 # 示例3:lt1 = ['aaaaaaaa','bbbbb','cccccc','ddd']得到如下效果:['aaaaaaaa','cccccc'] 46 47 lt1 = ['aaaaaaaa','bbbbb','cccccc','ddd'] 48 49 print(list(filter(lambda x: len(x) > 5,lt1)))
高階函數以及匿名函數之間的配合使用(練習):
1 '''模板一:lambda和filter的配合使用''' 2 # 需求:lt = [1,2,3,4,5,6,7,8,9] --> 得到[3,6,9] 3 4 print(list(filter(lambda x: x % 3 == 0,lt))) 5 6 7 '''模板二:lambda 和map的配合使用''' 8 # 需求:演示開平方操作 --> 容器對象:range 9 10 mo = map(lambda x: x ** 2,range(5)) 11 print(list(mo)) 12 13 14 '''模板三:在模板二的基礎上進行功能擴展:range(10),過濾以後保留的數據範圍大小為:(5,50)之間''' 15 16 mo = map(lambda x: x ** 2,range(10)) 17 fo = filter(lambda x: x > 5 and x < 50,mo) 18 print(list(fo)) 19 20 21 '''模板四:lambda 和reduce配合使用''' 22 # 求和值 23 import functools 24 25 lt = [1,2,3,4,5] 26 27 my_sum = functools.reduce(lambda x,y: x + y,lt) 28 print(my_sum) 29 30 31 '''模板五:求兩個列表對象中元素的和,返回新列表: 32 lt1 = [1,2,3,4], lt2 = [5,6,7,8], 結果:lt3 = [6,8,10,12]''' 33 34 mo = map(lambda x,y: x + y,lt1,lt2) 35 print(list(mo)) 36 37 38 '''模板六:求字元串中每個單詞的長度content = "welcome to shanghai", 結果:[7,2,8]''' 40 # 使用切割的思想:切完之後得到一個列表對象,內部元素["welcome","to","shanghai"] 41 words_list = content.split() 42 mo = map(len,words_list) 43 print(list(mo))