1、一般用法
filter()函數被用於過濾序列,它會過濾掉不符合條件的數據,符合條件的數據將會被留下,filter函數返回的結果是一個可迭代對象。
之所以稱它為高級語法,因為想要正確理解使用它並不容易,同時還要配合上lambda表達式。
filter的語法如下
filter(function, iterable)
function 是判斷函數,filter會遍歷iterable里的每一個數據,用function進行判斷,如果符合條件,才會被留下。
iterable 是可迭代對象,如列表,元組,甚至集合都可以
下面是一個簡單的使用示例
from collections import Iterable lst = [1, 2, 5, 6, 7] res = filter(lambda x: x % 2 == 0, lst) # res 是一個可迭代對象 print(isinstance(res, Iterable), type(res)) for item in res: print(item)
程序輸出結果
True <class 'filter'>
2
6
理解代碼的關鍵有3點
1. filter 做了什么
filter函數會遍歷列表lst, 用lambda表達式來判斷所遍歷到的數據是否符合要求
2. lambda 表達式做了什么
列表lst中的數據會逐個傳給lambda表達式進行判斷,lambda表達式返回這些數是否為2的倍數,盡管沒有return語句,但lambda表達式默認返回 x % 2 == 0 的結果
3. filter函數的返回值是什么
filter函數的返回值是一個可迭代對象,這一點很關鍵,這也是為什么我說filter函數是高級語法的原因。
為什么不返回列表?,如果返回的是列表,那么在filter函數執行過程中,就必須對列表里的每一個數據進行對2取模運算,這樣很浪費空間,因此filter在實現時采用了迭代器技術,將計算延遲到對filter函數返回結果進行遍歷時才進行。
怎么驗證上面的說法呢,對代碼稍加修改
from collections import Iterable def func(x): print("接收參數" + str(x)) return x%2 == 0 lst = [1, 2, 5, 6, 7] res = filter(func, lst) # res 是一個可迭代對象 print(isinstance(res, Iterable), type(res)) for item in res: print(item)
現在,我不使用lambda表達式對數據進行判斷,而是使用自由度更高的函數,在函數func中,我輸出接收到的參數,如果對lst數據中的過濾發生執行filter函數期間,那么,在輸出res類型之前,就會執行函數func中的print語句,現在來看程序實際的執行結果
True <class 'filter'>
接收參數1
接收參數2
2
接收參數5
接收參數6
6
接收參數7
程序輸出結果表明,在執行filter函數時,並沒有調用func函數對lst中的數據進行過濾,而是在對res進行遍歷時才調用func函數進行過濾
2.結合偏函數,更加強大
單純的使用filter函數,就已經很強大了,結合了偏函數,則更加強大
from functools import partial def even(x): return x%2 == 0 # 創建一個專門用來過濾保留偶數的函數 even_filter = partial(filter, even) lst = [1, 2, 5, 6, 7] res = even_filter(lst) for item in res: print(item)
通過使用偏函數partial,我創建了一個專門用來過濾保留偶數的函數,其實最終還是調用執行了filter(even, lst),但使用even_filter時,我們可以不用去管函數even,在創建even_filter時,已經約定even作為filter的第一個參數來使用了。