TL;DRlambda x: x + 1 就是一個沒有名字、只能裝一句運算式的函式。它真正好用的場合很窄,就是 sorted(words, key=lambda w: len(w)) 這種「當場給一個怎麼比的小函式、用完就丟」。一旦你想把它存進變數取名字,PEP 8 會叫你改用 def——因為要取名字,它就不該是 lambda 了。還有迴圈裡 [lambda: i for i in range(3)] 會三個都回 2,這個之後講。

lambda 的語法五分鐘就學得會。一個 lambda、接參數、一個冒號、收在一句運算式:

add_one = lambda x: x + 1
add_one(5)        ## 6

它就是一個函式,跟 def 做出來的東西同一種型別。差別是它沒有名字,而且身體只能放一句運算式——不能有 if 陳述句、不能 for、不能指派變數、不能寫成好幾行。(這裡指的是 if: 陳述句;a if c else b 那種條件運算式本身算一句運算式,照樣能放。)等於 def 拿掉名字、再拿掉「能寫好幾行」的能力。

所以難的從來不是語法,是「那這東西到底什麼時候該用」。我自己的答案大概是:很少,但有幾個場合它剛剛好。

它真正的家:key=

lambda 最名正言順的用途,是丟給 sortedmaxminkey。這些函式需要你告訴它「東西要怎麼比」,而那個「怎麼比」常常就是一句話的事,當場寫一個、用完就丟,根本不值得特地 def 一個出來:

words = ["banana", "kiwi", "apple"]
sorted(words, key=lambda w: len(w))
## ['kiwi', 'apple', 'banana']   依長度排

pairs = [("a", 3), ("b", 1), ("c", 2)]
sorted(pairs, key=lambda p: p[1])
## [('b', 1), ('c', 2), ('a', 3)]   依第二個元素排

這就是 lambda 的甜蜜點:那個小函式只在這一行活著,離開這行就什麼都不是。

PEP 8 明講:別把 lambda 綁給名字

很多人學會 lambda 之後,第一件就寫成這樣:

double = lambda x: x * 2

這個寫法 PEP 8 直接點名不要。要給函式取名字,就用 def。原因不是死規定,是真的有差——綁給變數的 lambda,名字會掉:

double = lambda x: x * 2
double.__name__        ## '<lambda>'

def double(x): return x * 2
double.__name__        ## 'double'

<lambda> 這個名字在 traceback 裡完全幫不上忙。程式炸的時候,你想看到的是 double,不是一排長得一樣的 <lambda>,認不出是哪個。def 只多打幾個字,但換來一個有意義的名字、可以寫文件字串、之後要加邏輯也擴得開。

這條其實可以反過來當判斷法用:你一旦想給它取名字,就代表它不該是 lambda 了。

很多 map/filter 其實寫成推導式更好讀

lambda 另一個常見出沒地是 mapfilter

xs = [1, 2, 3, 4]
list(map(lambda x: x * 2, xs))            ## [2, 4, 6, 8]
list(filter(lambda x: x % 2 == 0, xs))    ## [2, 4]

這兩行都能跑,但同樣的事用列表推導式寫,少一層 lambdalist() 包裝,通常更好讀:

[x * 2 for x in xs]                ## [2, 4, 6, 8]
[x for x in xs if x % 2 == 0]      ## [2, 4]

現在我 map/filter 配 lambda 用得越來越少,多半改推導式。這塊如果想多看一點,可以翻 Python 列表推導式:一行取代 for 迴圈,它跟 map/filter 蓋的範圍其實高度重疊。

迴圈裡的陷阱:三個都回 2

這個值得單獨講,因為踩到會 debug 很久。你在迴圈裡生一串 lambda,想說每個記住當下的 i

funcs = [lambda: i for i in range(3)]
[g() for g in funcs]
## [2, 2, 2]      不是 [0, 1, 2]

三個 lambda 全回 2。因為 lambda 沒有在當下把 i 的值記下來,它只記住「去外面找一個叫 i 的變數」,等你真的呼叫的時候迴圈早就跑完了,i 停在最後的 2。這叫晚綁定(late binding),不是 lambda 獨有,但 lambda 寫在迴圈裡特別容易撞上。

要它記住當下的值,用預設參數把 i 釘進去:

funcs = [lambda i=i: i for i in range(3)]
[g() for g in funcs]
## [0, 1, 2]

i=i 看起來怪,但它在「定義那一刻」就把當下的 i 抓成預設值,所以每個 lambda 各記各的。知道這招,省得哪天對著三個一樣的數字發呆。

所以,該用的時候其實不多

把上面收一收,判斷其實就兩條:要不要給它取名字?要的話用 def。會不會在別的地方再用一次?會的話用 def。剩下那種「就這一行、當場給 sorted 一個 key、寫完就忘」的小東西,才輪到 lambda——擺在那個位置,它確實比 def 俐落。

說穿了 lambda 不是拿來省 def 的,是拿來寫那些不值得有名字的函式。


本文範例都在 Python 3.14.3 上實際跑過。想看源頭的話:PEP 8 — Style Guide for Python Code(裡面 Programming Recommendations 那段講了別把 lambda 綁給名字)、Python 官方教學 4.7.5 — Lambda Expressions