<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Lambda on KbWen Blog</title>
    <link>https://www.kbwen.com/tags/lambda/</link>
    <description>KbWen 的個人技術部落格，分享 Python、機器學習、深度學習、資料工程與 AI 開發的學習筆記與實作心得。</description>
    <generator>Hugo</generator>
    <language>zh-tw</language>
    <image>
      <url>https://www.kbwen.com/images/og-default.png</url>
      <title>KbWen Blog</title>
      <link>https://www.kbwen.com/</link>
    </image>
    
    <lastBuildDate>Sun, 28 Jun 2026 07:00:00 +0800</lastBuildDate><atom:link href="https://www.kbwen.com/tags/lambda/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Python lambda 什麼時候該用、什麼時候別用</title>
      <link>https://www.kbwen.com/python-lambda/</link>
      <pubDate>Sun, 28 Jun 2026 07:00:00 +0800</pubDate><dc:creator>KbWen</dc:creator>
      <guid>https://www.kbwen.com/python-lambda/</guid>
      <description>lambda 語法五分鐘學得會，難的是什麼時候用。聊它真正的家（sorted 的 key=）、PEP 8 為什麼叫你別把它綁給變數，還有迴圈裡三個 lambda 都回同一個值的陷阱。</description>
      <content:encoded><![CDATA[<blockquote>
<p><strong>TL;DR</strong>：<code>lambda x: x + 1</code> 就是一個沒有名字、只能裝一句運算式的函式。它真正好用的場合很窄，就是 <code>sorted(words, key=lambda w: len(w))</code> 這種「當場給一個怎麼比的小函式、用完就丟」。一旦你想把它存進變數取名字，<a href="https://peps.python.org/pep-0008/">PEP 8</a> 會叫你改用 <code>def</code>——因為要取名字，它就不該是 lambda 了。還有迴圈裡 <code>[lambda: i for i in range(3)]</code> 會三個都回 2，這個之後講。</p>
</blockquote>
<p>lambda 的語法五分鐘就學得會。一個 <code>lambda</code>、接參數、一個冒號、收在一句運算式：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">add_one</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl"><span class="n">add_one</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>        <span class="c1">## 6</span>
</span></span></code></pre></div><p>它就是一個函式，跟 <code>def</code> 做出來的東西同一種型別。差別是它沒有名字，而且身體只能放<strong>一句運算式</strong>——不能有 <code>if</code> 陳述句、不能 <code>for</code>、不能指派變數、不能寫成好幾行。（這裡指的是 <code>if:</code> 陳述句；<code>a if c else b</code> 那種條件運算式本身算一句運算式，照樣能放。）等於 <code>def</code> 拿掉名字、再拿掉「能寫好幾行」的能力。</p>
<p>所以難的從來不是語法，是「那這東西到底什麼時候該用」。我自己的答案大概是：很少，但有幾個場合它剛剛好。</p>
<h2 id="它真正的家key">它真正的家：<code>key=</code></h2>
<p>lambda 最名正言順的用途，是丟給 <code>sorted</code>、<code>max</code>、<code>min</code> 當 <code>key</code>。這些函式需要你告訴它「東西要怎麼比」，而那個「怎麼比」常常就是一句話的事，當場寫一個、用完就丟，根本不值得特地 <code>def</code> 一個出來：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">words</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;banana&#34;</span><span class="p">,</span> <span class="s2">&#34;kiwi&#34;</span><span class="p">,</span> <span class="s2">&#34;apple&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">sorted</span><span class="p">(</span><span class="n">words</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">w</span><span class="p">:</span> <span class="nb">len</span><span class="p">(</span><span class="n">w</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="c1">## [&#39;kiwi&#39;, &#39;apple&#39;, &#39;banana&#39;]   依長度排</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">pairs</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">&#34;a&#34;</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="p">(</span><span class="s2">&#34;b&#34;</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s2">&#34;c&#34;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl"><span class="nb">sorted</span><span class="p">(</span><span class="n">pairs</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">p</span><span class="p">:</span> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="c1">## [(&#39;b&#39;, 1), (&#39;c&#39;, 2), (&#39;a&#39;, 3)]   依第二個元素排</span>
</span></span></code></pre></div><p>這就是 lambda 的甜蜜點：那個小函式只在這一行活著，離開這行就什麼都不是。</p>
<h2 id="pep-8-明講別把-lambda-綁給名字">PEP 8 明講：別把 lambda 綁給名字</h2>
<p>很多人學會 lambda 之後，第一件就寫成這樣：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">double</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span> <span class="o">*</span> <span class="mi">2</span>
</span></span></code></pre></div><p>這個寫法 <a href="https://peps.python.org/pep-0008/">PEP 8</a> 直接點名不要。要給函式取名字，就用 <code>def</code>。原因不是死規定，是真的有差——綁給變數的 lambda，名字會掉：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">double</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span> <span class="o">*</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl"><span class="n">double</span><span class="o">.</span><span class="vm">__name__</span>        <span class="c1">## &#39;&lt;lambda&gt;&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">double</span><span class="p">(</span><span class="n">x</span><span class="p">):</span> <span class="k">return</span> <span class="n">x</span> <span class="o">*</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl"><span class="n">double</span><span class="o">.</span><span class="vm">__name__</span>        <span class="c1">## &#39;double&#39;</span>
</span></span></code></pre></div><p><code>&lt;lambda&gt;</code> 這個名字在 traceback 裡完全幫不上忙。程式炸的時候，你想看到的是 <code>double</code>，不是一排長得一樣的 <code>&lt;lambda&gt;</code>，認不出是哪個。<code>def</code> 只多打幾個字，但換來一個有意義的名字、可以寫文件字串、之後要加邏輯也擴得開。</p>
<p>這條其實可以反過來當判斷法用：<strong>你一旦想給它取名字，就代表它不該是 lambda 了。</strong></p>
<h2 id="很多-mapfilter-其實寫成推導式更好讀">很多 <code>map</code>/<code>filter</code> 其實寫成推導式更好讀</h2>
<p>lambda 另一個常見出沒地是 <code>map</code> 跟 <code>filter</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">xs</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">list</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span> <span class="o">*</span> <span class="mi">2</span><span class="p">,</span> <span class="n">xs</span><span class="p">))</span>            <span class="c1">## [2, 4, 6, 8]</span>
</span></span><span class="line"><span class="cl"><span class="nb">list</span><span class="p">(</span><span class="nb">filter</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">,</span> <span class="n">xs</span><span class="p">))</span>    <span class="c1">## [2, 4]</span>
</span></span></code></pre></div><p>這兩行都能跑，但同樣的事用列表推導式寫，少一層 <code>lambda</code> 跟 <code>list()</code> 包裝，通常更好讀：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="p">[</span><span class="n">x</span> <span class="o">*</span> <span class="mi">2</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">xs</span><span class="p">]</span>                <span class="c1">## [2, 4, 6, 8]</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">xs</span> <span class="k">if</span> <span class="n">x</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">]</span>      <span class="c1">## [2, 4]</span>
</span></span></code></pre></div><p>現在我 <code>map</code>/<code>filter</code> 配 lambda 用得越來越少，多半改推導式。這塊如果想多看一點，可以翻 <a href="/python-list-comprehension/">Python 列表推導式：一行取代 for 迴圈</a>，它跟 <code>map</code>/<code>filter</code> 蓋的範圍其實高度重疊。</p>
<h2 id="迴圈裡的陷阱三個都回-2">迴圈裡的陷阱：三個都回 2</h2>
<p>這個值得單獨講，因為踩到會 debug 很久。你在迴圈裡生一串 lambda，想說每個記住當下的 <code>i</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">funcs</span> <span class="o">=</span> <span class="p">[</span><span class="k">lambda</span><span class="p">:</span> <span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">g</span><span class="p">()</span> <span class="k">for</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">funcs</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="c1">## [2, 2, 2]      不是 [0, 1, 2]</span>
</span></span></code></pre></div><p>三個 lambda 全回 2。因為 lambda 沒有在當下把 <code>i</code> 的值記下來，它只記住「去外面找一個叫 <code>i</code> 的變數」，等你真的呼叫的時候迴圈早就跑完了，<code>i</code> 停在最後的 2。這叫晚綁定（late binding），不是 lambda 獨有，但 lambda 寫在迴圈裡特別容易撞上。</p>
<p>要它記住當下的值，用預設參數把 <code>i</code> 釘進去：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">funcs</span> <span class="o">=</span> <span class="p">[</span><span class="k">lambda</span> <span class="n">i</span><span class="o">=</span><span class="n">i</span><span class="p">:</span> <span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">g</span><span class="p">()</span> <span class="k">for</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">funcs</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="c1">## [0, 1, 2]</span>
</span></span></code></pre></div><p><code>i=i</code> 看起來怪，但它在「定義那一刻」就把當下的 <code>i</code> 抓成預設值，所以每個 lambda 各記各的。知道這招，省得哪天對著三個一樣的數字發呆。</p>
<h2 id="所以該用的時候其實不多">所以，該用的時候其實不多</h2>
<p>把上面收一收，判斷其實就兩條：要不要給它取名字？要的話用 <code>def</code>。會不會在別的地方再用一次？會的話用 <code>def</code>。剩下那種「就這一行、當場給 <code>sorted</code> 一個 key、寫完就忘」的小東西，才輪到 lambda——擺在那個位置，它確實比 <code>def</code> 俐落。</p>
<p>說穿了 lambda 不是拿來省 <code>def</code> 的，是拿來寫那些不值得有名字的函式。</p>
<hr>
<p><em>本文範例都在 Python 3.14.3 上實際跑過。想看源頭的話：<a href="https://peps.python.org/pep-0008/">PEP 8 — Style Guide for Python Code</a>（裡面 Programming Recommendations 那段講了別把 lambda 綁給名字）、<a href="https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions">Python 官方教學 4.7.5 — Lambda Expressions</a>。</em></p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
