名前をつけるまでもない関数
Python で関数を作るときは、たいてい def を使って名前をつけ、使い回せるようにファイル内に定義します。一方の lambda は、それをぐっとコンパクトにした無名関数です。わざわざ def で関数を定義するほどでもない、そんな場面でサッと書けるのが魅力です。
まずは両者を並べて、その形を見てみましょう。
同じ処理をするふたつの関数を見比べてみましょう。lambda 版が 1 行に収まっているのは、まさにそれが存在意義だからです。つまり、使い捨ての場面でサクッと使う、使い捨ての関数というわけですね。
構文
lambda <params>: <expression>
<params>はdefで書くときと同じ引数リストです。デフォルト値や*args、**kwargsもそのまま使えます。<expression>は式をひとつだけ書きます。その評価結果がそのまま戻り値になります。
具体例を見てみましょう。
return は書きません。式の値がそのまま戻り値になります。
lambda の唯一の制約
lambda に書けるのは 1 つの式だけです。文(ステートメント)は入れられません。
ただし、三項演算子なら使えます。
もし式を 2 つ以上書きたくなったら、それは def に切り替えるサインです。
lambda が本当に活きる場面
変数に代入して使う lambda は、名前付きの def に比べてほぼ間違いなく見劣りします。
これは def double(x): return x * 2 と比べて完全に劣っています。読みやすさは変わらないうえに、lambda 版だとスタックトレースに <lambda> というありがたくない名前が出てくるので、デバッグ時にかえって不便です。
python の lambda が本領を発揮する場面はひとつだけ。高階関数にインラインで渡す引数として使うときです。
sorted の key に lambda を渡す
定番の使い方がこれです。
sorted の key には「要素を受け取って、並び替えに使う値を返す関数」を渡します。この用途なら一行で書けるラムダ式がぴったりで、わざわざ def で名前付き関数を定義するのは大げさに感じるはずです。
タプルを返すようにすれば、複数のキーでまとめて並び替えることもできます:
min・max・filter・map での活用
これらの組み込み関数も、オプションで関数を引数に取るという点で同じ話です。
map や filter を使う場面では、リスト内包表記の方がスッキリ書けることがほとんどです。
ほとんどのPythonistaが map や filter より内包表記を好むのは、こうした理由からです。一方で sorted、min、max のように内包表記で書き換えるショートカットがない場面では、lambda がやはりしっくりきます。
lambda と operator モジュール
「キーを取り出すだけ」「属性を取り出すだけ」といった用途のlambdaなら、Python標準の operator モジュールのほうが速くて読みやすい代替になります。
大きな差ではありませんが、すでに operator をインポートしているコードなら、こちらの方が少し宣言的に読めます。
def に戻すべきケース
次のどれかに当てはまるなら、素直に def で書きましょう。
- ロジックが1つの式にすっきり収まらない。
- 関数に名前を付けた方が可読性が上がる。
- 同じロジックを複数箇所で使う。
- docstring を付けたい(ラムダには docstring を持たせられません)。
覚えておきたいのは、Python は行数を競うものではないということ。ロジックが少しでも複雑になってきたら、1行の lambda より3行の名前付き関数の方が、ほぼ間違いなく読みやすくなります。
次は:デコレータ
lambda は関数を「値」として持ち回るための道具でした。デコレータはこの発想をさらに一歩進めて、任意の関数をログ出力・計測・キャッシュ・認証といった再利用可能な振る舞いで包めるようにします。しかも、その関数の上の行に @ を1つ書くだけ。次のページで扱います。
よくある質問
Pythonのlambdaとは何ですか?
lambdaは1行で書ける「名前のない関数」です。たとえば lambda x: x * 2 は def double(x): return x * 2 と中身は同じで、違うのは名前が付いていないという点だけ。他の関数に引数として小さな関数を渡したいときに一番力を発揮します。
defではなくlambdaを使うべき場面は?
sorted や max、filter などに直接渡すような、その場限りで1行の式で済む関数なら lambda が向いています。処理が複数行にわたる場合や、名前を付けたくなるようなロジックなら素直に def を使いましょう。名前付き関数の方が結局読みやすいことがほとんどです。
lambdaにはどんな制限がありますか?
lambda に書けるのは1つの式だけで、文(statement)は置けません。代入も if ブロックも多行ロジックも不可です(三項演算子の a if cond else b は使えます)。この制約と戦い始めたら、def に切り替えるサインです。