第 18 課 · 進階 · 18 分鐘

Python Lambda、map 與 filter

寫簡短函式,不寫迴圈也能轉換序列。

lambda 語法map 與 filter惰性迭代器

收銀機導出一串訂單,Maya 想按每杯單價排序。為一行比較專門寫個具名函式,好像有點小題大做。lambda 什麼時候才值得出場?

lambda 是一個小型匿名函式。map 和 filter 會把函式應用到序列上,但在 Python 3 中回傳的是惰性迭代器。想查看全部結果時,先轉成列表。操作很簡單時,推導式往往更清楚。 你還會看到 lambda 的延遲綁定、一次性迭代器,以及用 key 代替 map 後再排序。

lambda 是短函式

lambda 參數: 表達式 可以不用 def 程式碼區塊就建立函式。它適合作為一行規則傳給另一個函式。如果邏輯需要名字、多個步驟或文件字串,就改用 def。

double = lambda n: n * 2
print(double(4))
print((lambda a, b: a + b)(2, 3))

小型匿名函式

map 轉換每個元素

map(function, iterable) 會對每個元素呼叫一次函式。Python 3 中結果是迭代器,所以要用 list() 包起來才能列印全部值。原序列不會被修改。

nums = [1, 2, 3]
print(list(map(lambda n: n + 1, nums)))
print(nums)

惰性的 map

filter 保留比對項

filter(predicate, iterable) 只保留謂詞回傳 True 的元素。謂詞可以是 lambda,也可以是具名函式。列印或索引前,先把結果轉成列表。

nums = [1, 2, 3, 4]
even = filter(lambda n: n % 2 == 0, nums)
print(list(even))

保留符合條件的值

lambda 在呼叫時才查變數

lambda 在被呼叫時才尋找自由變數,而不是建立時。迴圈裡建立的多個 lambda 都引用同一個 n,就都會看到最後的值。需要各自儲存目前值時,用預設參數捕獲。

funcs = [lambda: n for n in range(3)]
print([fn() for fn in funcs])
fixed = [lambda n=n: n for n in range(3)]
print([fn() for fn in fixed])

用預設參數綁定目前迴圈值

map 和 filter 只能消費一次

map() 和 filter() 回傳迭代器,不是列表。消費完就耗盡。需要查看或重複使用時轉成列表;不需要時,直接交給 sum() 或 any(),它們也只消費一次。

numbers = map(lambda n: n * 2, [1, 2, 3])
print(list(numbers))
print(list(numbers))
filtered = filter(lambda n: n > 1, [1, 2, 3])
print(any(filtered))
print(any(filtered))

耗盡的迭代器不會重新開始

用 key,不要先 map 再排序

只需要極值或順序時,把 key 函式直接交給 min、max 或 sorted。單獨構造一個映射列表會多一步,還可能丟掉原記錄。lambda 只寫一個短表達式;規則需要名字時改用 def。

orders = [("latte", 4.5), ("tea", 3.0), ("mocha", 5.0)]
cheapest = min(orders, key=lambda item: item[1])
names = sorted(orders, key=lambda item: item[1], reverse=True)
print(cheapest)
print([name for name, price in names])

保留記錄,傳入規則

本課要點

  • lambda 用來建立小型匿名函式。
  • map 對每個元素應用函式,並回傳迭代器。
  • filter 保留謂詞為真的元素。
  • 列表推導式通常比 map 或 filter 更容易讀。
  • lambda 延遲綁定;迭代器只消費一次;key 函式能保留原記錄。

常見錯誤

  • 直接列印 map 或 filter 物件,卻期待看到列表。
  • 邏輯很複雜時仍然硬寫 lambda,而不是用具名函式。
  • 忘記 map 和 filter 在被消費前是惰性的。
  • 對映射後的價格列表排序,結果丟掉了飲料名。
輪到你

用 map 和 filter 把 [1, 2, 3, 4, 5] 中的偶數平方。

動手試試

改改變數、先預測輸出,再執行程式碼。第一次點擊「執行程式碼」時會下載 Python 執行時,可能需要幾秒鐘。

瀏覽器內 Python本機執行 · 無需帳號
首次執行會從 CDN 下載 Pyodide。修改後點擊「執行程式碼」。

練習本課

12 道題,作答後立即看到解釋。

查看 12 道題答案開始練習
← 巢狀資料遞迴 →