1、map
python內建了map()函式,map()函式接受兩個引數,乙個是函式,乙個是iterable,map將傳入的函式依次作用到序列的每乙個元素上,並把結果作為新的iterator返回。
舉例說明,比如我們有乙個函式f(x)=x*2,要把這個函式作用在乙個list[1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map()實現。
>>> def f(x):
... return x*2
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[2, 4, 6, 8, 10, 12, 14, 16, 18]
map()傳入的第乙個引數是f,即函式物件本身。由於結果r是乙個iterator,iterator是惰性序列,因此通過list()函式讓它把整個序列都計算出來並返回乙個list。
你可能會想,不需要map()函式,寫乙個迴圈,也可以計算出結果:
l =
for i in [1, 2, 3, 4, 5, 6, 7, 8, 9]:
print(l)
的確也可以,但是,從上面的迴圈**,能一眼看明白」把f(x)作用在list的每乙個元素並把結果生成乙個新的list「嗎?
所以,map()作為高階函式,事實上它把運算規則抽象了,因此,我們不但可以計算簡單的f(x)=x*2,還可以計算任意複雜的函式,比如把這個list所有的數字轉為字串:
>>> list(map(str,[1, 2, 3, 4, 5, 6, 7, 8, 9]))
['1', '2', '3', '4', '5', '6', '7', '8', '9']
只需要一行**就可以搞定。
2、reduce
再看reduce的用法。reduce是把乙個函式作用在乙個序列[x1, x2, x3……]上,這個函式必須接收兩個引數,reduce把結果繼續和序列的下乙個元素做累計計算。簡單來說,就是先計算x1和x2的結果,再拿結果與x3計算,依次類推。
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1,x2), x3), x4)
比如說乙個序列求和,就可以用reduce實現。
>>> from functools import reduce
>>> def add(x, y):
... return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25
當然求和運算可以直接使用python內建函式sum(),沒必要動用reduce。
但是如果要把序列[1, 3, 5, 7, 9]變換為整數13579,reduce就可以派上用場:
>>> from functools import reduce
>>> def fn(x, y):
... return x * 10 + y
...
>>> reduce(fn, [1, 3, 5, 7, 9])
13579
這個例子本身沒多大用處,但是,如果考慮到字串str也是乙個序列,對上面的例子稍加改動,配合map,我們就可以寫出把str轉換為int的函式:
>>> from functools import reduce
>>> def fn(x, y):
... return x * 10 + y
...>>> def char2num(s):
... digits =
... return digits[s]
...>>> reduce(fn, map(char2num, '13579'))
13579
from functools import reduce
digits =
def str2int(s):
def fn(x, y):
return x * 10 + y
def char2num(s):
return digits[s]
return reduce(fn, map(char2num, s))
還可以用lambda函式進一步簡化成:
from functools import reduce
digits =
def char2num(s):
return digits[s]
def str2int(s):
return reduce(lambda x, y: x * 10 + y, map(char2num, s))
也就是說,假設python沒有提供int()函式,你完全可以自己寫乙個把字串轉化為整數的函式,而且只需要幾行**。
3、filter
python內建的filter()函式用於過濾序列。
和map()類似,filter()也接收乙個函式和乙個序列。和map()不同的是,filter()把傳入的函式依次作用於每乙個元素,然後根據返回值是true還是false決定保留還是丟棄該元素。
例如,在乙個list中,刪掉偶數,只保留奇數,可以這麼寫:
def is_odd(n):
return n % 2 == 1
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
# 結果: [1, 5, 9, 15]
把乙個序列中的空字串刪掉,可以這麼寫:
def not_empty(s):
return s and s.strip()
list(filter(not_empty, ['a', '', 'b', none, 'c', ' ']))
# 結果: ['a', 'b', 'c']
可見用filter()這個高階函式,關鍵在於正確實現乙個篩選函式。
注意到filter()函式返回的是乙個iterator,也就是乙個惰性序列,所有要強迫filter()完成計算結果,需要用list()函式獲得所有結果並返回list。
4、sorted
排序也是在程式中經常用到的演算法。無論使用氣泡排序還是快速排序,排序的核心是比較兩個元素的大小。如果是數字,我們可以直接比較,但如果是字串或者兩個dict呢?直接比較數學上的大小是沒有意義的,因此,比較的過程必須通過函式抽象出來。
python內建的sorted()函式就可以對list進行排序:
>>> sorted([36, 5, -12, 9, -21])
[-21, -12, 5, 9, 36]
此外,sorted()函式也是乙個高階函式,它還可以接收乙個key函式來實現自定義的排序,例如按絕對值大小排序:
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]
key指定的函式將作用於list的每乙個元素上,並根據key函式返回的結果進行排序。
我們再看乙個字串排序的例子:
>>> sorted(['bob', 'about', 'zoo', 'credit'])
['credit', 'zoo', 'about', 'bob']
預設情況下,對字串排序,是按照ascii的大小比較的,由於'z' < 'a',結果,大寫字母z會排在小寫字母a的前面。
現在,我們提出排序應該忽略大小寫,按照字母序排序。要實現這個演算法,不必對現有**大加改動,只要我們能用乙個key函式把字串對映為忽略大小寫排序即可。忽略大小寫來比較兩個字串,實際上就是先把字串都變成大寫(或者都變成小寫),再比較。
這樣,我們給sorted傳入key函式,即可實現忽略大小寫的排序:
>>> sorted(['bob', 'about', 'zoo', 'credit'], key=str.lower)
['about', 'bob', 'credit', 'zoo']
要進行反向排序,不必改動key函式,可以傳入第三個引數reverse=true:
>>> sorted(['bob', 'about', 'zoo', 'credit'], key=str.lower, reverse=true)
['zoo', 'credit', 'bob', 'about']
5、小結
高階函式的抽象能力是非常強大的,在**中善於利用這些高階函式,可以使我們的**變得簡潔明瞭。
Python常用高階函式
高階函式是在python中乙個非常有用的功能函式,所謂高階函式就是乙個函式可以用來接收另乙個函式作為引數,這樣的函式叫做高階函式。為了便於理解,我們從實際例子來看看函式當做引數被傳遞到另個函式是什麼樣的。我們把abs 函式賦值給了f變數,接下來你就可以像使用abs 函式本身那樣使用f變數了,區別只是...
python 函式4(遞迴 高階函式)
python 函式4 遞迴 高階函式 遞迴 在函式內部,可以呼叫其他函式。如果乙個函式在內部呼叫自身本身,這個函式就是遞迴函式。遞迴特性 1.遞迴必須有乙個明確的結束條件 2.每次進入更深一層遞迴時,問題規模相比上次遞迴都應有所減少 3.遞迴效率不高,遞迴層次過多會導致棧溢位 在計算機中,函式呼叫是...
python中5個常用的內建高階函式
python內建常用高階函式 一 函式式程式設計 1 map 函式 是 python 內建的高階函式,它接收乙個函式 f 和乙個 list,並通過把函式 f 依次作用在 list 的每個元素上,得到乙個新的 list 並返回 def add x return x x print map add,1 ...