高階函數Higher-order function
函數的參數, 可以接收變數, 而函數就是變數, 那麼就可以把函數傳給另一個函數的參數
def math(f, x, y): if f==abs: return f(x)+f(y) else: return f(x, y) print(math(abs, -10, 5)) print(math(pow, 2,10))
上面代碼中, 將abs傳入math函數中, 由math的 f 接收, 所以 f 就變成了abs() 的功能了. 若將pow傳入add, 那麼 f 就變成了pow() 的功能.
所以, 我們就可以定義, 假如有一個函數, 他的任何一個參數是用來接收其他的函數, 那麼這的函數就稱為高階函數, 比如上面所說的 math函數, 就是高階函數. 常見的系統高階函數有map, reduce, filter, sorted
map
Python有一個蠻好用的函數 – map. 此函數接收二個參數, 第一個參數為另一個函數名, 第二個參數為Iterable, 比如
r=map(f, [1,2,3,4,5])
如此就會把list裏的元素, 一個一個傳入f去計算, 然後回傳一個Generator給r, 所以再用list把Generator一個一個計算出來. 如果f 是計算x2, 就會傳回 1,4,9,16,25. 如果f 是str, 就會把 數字轉成字串
def f(x): return x*x r=map(f, [1,2,3,4,5]) print(list(r)) r=map(str, [1,2,3,4,5]) print(list(r)) 結果 : [1, 4, 9, 16, 25] ['1', '2', '3', '4', '5']
map()即為高階函數, 它把運算規則抽象化, 不但可計算List裏面所有元素的x2值, 也可將List裏的元素全轉為字串, 當然還可以作其他的事, 只需將函數傳入即可.
reduce
reduce的語法及其定義如下
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
由上可知, reduce是先把x1, x2 傳給 f 計算, 再把結果與 x3 傳給 f 計算, 然後再把結果與 x4 傳給 f 計算
reduce的應用, 使用下面代碼說明, 可計算 1+2+3+…+100的值
m=list(range(1,101)) def f(x, y): return x+y; print(reduce(f, m))
下面的代碼, 有一資料 data 為dict, 使用map將dict裏的元素全轉為數字, 再使用reduce將前位數*10加上後位數, 就可以轉成一大串的整數
from functools import reduce data = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9} def toInt(dic): def fn(x, y): return x * 10 + y def stoi(s): return dic[s] return reduce(fn, map(stoi, dic)) print(toInt(data)) 結果 : 123456789
filter
語法如下
filter(fn, [x1, x2, x3, x4, x5])
演算法
將list裏的值依序傳入fn, 經fn計算後傳回True or False, 若傳回值為True, 則保留此元素, 若傳回值為False, 則刪除此元素
請注意, filter返回Iterator, 是惰性序列, 需使用list()函數返回list
下面的代碼可以將字串中的空格刪除掉. 請注意一下, 雖然Python不需宣告型別, 但還是得先宣告
tmp=”, 否則是無法使用的
def trim(s): if s==' ': return False else: return True str="This is a Book" tmp='' for s in filter(trim, str): tmp+=s print(tmp)
sorted
sorted為一排序函數, 傳入的參數為一List, 然後對List的元素作大小排序, 如下
print(sorted([10,-3,9,-22,15,80])) 結果 : [-22, -3, 9, 10, 15, 80]
同時sorted亦為一高階函數, 可將另一函數傳入key變數, 如下
print(sorted([10,-3,9,-22,15,80], key=abs)) #轉成絕對值再排序, 但輸出結果是有正負數的
print(sorted(['monkey', 'Pig', 'cat', 'dog'], key=str.lower))//轉成小寫再排序, 但輸出是有大小寫的
結果 :
[-3, 9, 10, 15, -22, 80]
['cat', 'dog', 'monkey', 'Pig']
反向排序則加入第三個參數 reverse=True
print(sorted(['monkey', 'Pig', 'cat', 'dog'], key=str.lower, reverse=True)) 結果 : ['Pig', 'monkey', 'dog', 'cat']