python內建的幾個高階函式
python中一切皆可以為物件;而高階函式的含義為其傳入的引數中包含函式物件,接收函式物件為引數的函式為高階函式。python中有幾個內建的高階函式,包括map(),sorted(),filter();早前的python版本中還有內建的reduce(),現在該函式被放在functools模組中了。
map()函式
在之前的文章中已經詳細講過了,詳情參考https://blog.csdn.net/Always_Go_/article/details/118425093
補充的一點:
對於大部分map()使用的場景,都已經可以用列表推導式簡便的替代,對於多個引數傳入的情形,一般需要轉換為下標的形式:
>>>a=[1,2,3]
>>>b=[10,20,30]
>>>[a[i]+b[i] for i in range(3)]
[11, 22, 33]
sorted()函式
提到sorted()函式必須要和sort()函式區分:
-
sorted()函式是內建函式,接收一個可迭代物件,對所有可迭代物件均可按照一定規則進行排序,會返回一個新的可迭代物件。
-
sort()函式是List物件的一個方法,直接修改原list,返回None
>>>a=[2,3,1]
>>>b=sorted(a)#返回新物件
>>>b
[1, 2, 3]
>>>a#原物件不改變
[2, 3, 1]
>>>a=[2,3,1]
>>>b=a.sort()#返回None
>>>a
[1, 2, 3]#改變原物件
>>>b
>>>sort(a)#內建方法只有sorted()
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'sort' is not defined
而sorted()函式本身非常有用,尤其和key結合起來。之所以sorted是高階函式,因為其內部引數可以接收一個函式物件。
>>>a=[1,-2,3,-1,10,-20]
>>>sorted(a)#預設從小排到大
[-20, -2, -1, 1, 3, 10]
>>>sorted(a,reverse=True)#從大排到小
[10, 3, 1, -1, -2, -20]
>>>sorted(a,key=lambda x:x**2)#key傳入一個函式物件,通過每個數的平方來排序
[1, -1, -2, 3, 10, -20]
對於多維列表排序:
>>>a=[[2,3,1],[10,-1,3],[-1,20,2]]
>>>sorted(a,key=lambda x:x[1])#根據每行第2個數進行排序
[[10, -1, 3], [2, 3, 1], [-1, 20, 2]]
對於字串排序:
>>>a=['hacca','de','djnhg']
>>>sorted(a,key=lambda x:x[-1])
['hacca', 'de', 'djnhg']
對於自定義的物件排序:
class A:
def __init__(self,a,b):
self.a=a
self.b=b
def __repr__(self):
return '%s_%s_%s'%(self.__class__.__name__,self.a,self.b)
>>>x=[A(1,2),A(-1,3),A(-10,1)]
>>>sorted(x,key=lambda x:x.a)
[A_-10_1, A_-1_3, A_1_2]
總之,sorted()函式配合key使用lambda匿名函式非常好用。
filter()函式
filter()顧名思義,為一個過濾函式;接收一個函式和一個可迭代物件,將函式依次作用在該可迭代物件上,其中函式每次必須返回True或者False.最後將返回為True的元素保留下來。
>>>a=[1,2,3,4,5]
>>>def func(x):
>>> return x%2==0
>>>list(filter(func,a))#a中的2和4傳入函式時返回為True,因此最後只剩下2和4
[2, 4]
>>>[x for x in [1,2,3,4,5] if x%2==0]#也可以用列表推到式實現
[2, 4]
舉一個相對比較複雜的例子。如何認定學生是否偏科呢?符合如下其中一條的學生,將被視為偏科:
-
有 2 科成績在 80 分以上,有一科在 60 分以下。
-
有 1 科成績在 90 分以上,另外 2 科成績都在 60 分以下。
-
有 1 科成績在 90 分以上,但三科的平均分在 70 分以下。
scores = [ ("Emma", 89 , 90 , 59),
("Edith", 99 , 49 , 59),
("Sophia", 99 , 60 , 20),
("May", 40 , 94 , 59),
("Ashley", 89 , 90 , 59),
("Arny", 89 , 90, 69),
("Lucy", 79 , 90 , 59 ),
("Gloria", 85 , 90 , 59),
("Abby", 89 , 91 , 90)]
def handle_filter(a):
s = sorted(a[1: ]) #對三科成績進行排序
#有 2 科成績在 80 分以上,並且有 1 科在 60 分以下的
if s[-2] > 80 and s[0] < 60 :
return True
#有 1 科成績在 90 分以上,另外 2 科成績都在 60 分以下
if s[-1] > 90 and s[1] < 60 :
return True
if s[-2] > 80 and sum(s)/len(s) < 60:
#有 1 科成績在 90 分以上, 且 3 科的平均分在 70 分以下
return True
return False
>>>list(filter(handle_filter, scores))
[('Emma', 89, 90, 59), ('Edith', 99, 49, 59), ('May', 40, 94, 59), ('Ashley', 89, 90, 59), ('Gloria', 85, 90, 59)]
可以看到,對於這樣規則比較複雜的過濾,用列表推導式會非常較為麻煩且程式碼易讀性會較差了,這個時候用filter還是更為好看的。但都比for迴圈要來得好。
reduce()函式
python3中reduce都已經在functools模組中,語法為:
reduce(function, sequence[, initial]) -> value
reduce函式接受一個function和一串sequence,並返回單一的值,以如下方式計算: 1.初始,function被呼叫,並傳入sequence的前兩個items,計算得到result並返回 2.function繼續被呼叫,並傳入上一步中的result,和sequence種下一個item,計算得到result並返回。一直重複這個操作,直到sequence都被遍歷完,返回最終結果。 注意. 當initial值被指定時,傳入step1中的兩個引數分別是initial值和sequence的第一個items。reduce()最多隻能接受三個引數,func,sequence,initial。
>>>reduce(lambda a,b:a+b,[1,2,3,4,5])#傳入的第一個值為1
15
>>>reduce(lambda a,b:a+b,[1,2,3,4,5],100)#傳入的第一個初始值為100
115