- lambda は、1 つの式に限定された匿名関数です。
- これは短い引数、特に
sorted、min、およびmaxに対するkeyとして使用するのが最適です。 - リストの内包は通常、ラムダを使用した
mapやfilterよりも明確です。 - 名前にラムダを割り当てる場合は、代わりに
defを記述します。
製品を価格順に並べ替える必要があります。 「価格を使用する」と言うためだけに別の名前付き関数を書くのは、かなりの儀式のように感じられます。 Python ラムダ関数 を使用すると、使用する場所でその小さなロジックをインラインで正確に定義できます。
ラムダは便利ですが、使いすぎるのも簡単です。このガイドでは、それらが実際に役立つ部分と、コードが読みにくくなる部分を示します。すべての例を Python 3.13 で実行し、示されている出力はその実行からのものです。
ラムダとは何ですか?
ラムダは名前のない関数であり、lambda キーワードで記述されます。
lambda arguments: expression
任意の数の引数を受け取り、単一の式の値を自動的に返します。 return キーワードやステートメントの本文はありません。
square = lambda x: x * x
print(square(4)) # 16
print((lambda a, b=10: a + b)(5)) # 15
2 行目では、デフォルトの引数を使用してラムダを定義し、それをすぐに呼び出します。これを実際のコードで記述することはほとんどありませんが、ラムダが通常の関数オブジェクトであることを示しています。
ラムダ vs デフ
これら 2 つは同じ動作をする関数を生成します。
square = lambda x: x * x
def square_def(x):
return x * x
print(square(4), square_def(4)) # 16 16
print(square.__name__, square_def.__name__) # <lambda> square_def
名前を見てください。すべてのラムダは <lambda> と呼ばれるだけなので、エラー メッセージやログからはどれが失敗したかが分かりません。これが、PEP 8 などのスタイル ガイドが関数に名前を付ける場合に def を推奨する主な理由です。
| 特徴 | ラムダ |
確かに |
|---|---|---|
| 名前 | 匿名 | 名前付き |
| 本体 | 一つの表現 | 任意の数のステートメント |
| 戻る | 暗黙的 | 明示的 return |
| ドキュメント文字列とタイプヒント | サポートされていません | サポートされています |
| 読み取り可能なトレースバック | <lambda>を表示します |
名前を表示します |
| こんな方に最適 | 短い使い捨て引数 | その他すべて |
キーによるソート: 最適な使用法
sorted、min、max などの関数は、比較対象を決定する key 関数を受け入れます。ここでラムダが威力を発揮します。
products = [("pen", 10), ("bag", 900), ("book", 250)]
sorted(products, key=lambda p: p[1])
# [('pen', 10), ('book', 250), ('bag', 900)]
max(products, key=lambda p: p[1])
# ('bag', 900)
いくつかの基準で並べ替えるには、タプルを返します。ここでは、人々が年齢順、最年長順、次に名前順に並べ替えられています。
people = [{"name": "Asha", "age": 31}, {"name": "Ben", "age": 25},
{"name": "Dev", "age": 31}]
[p["name"] for p in sorted(people, key=lambda p: (-p["age"], p["name"]))]
# ['Asha', 'Dev', 'Ben']
マイナス記号は数値のみの順序を逆にします。既存の関数がすでにその役割を果たしているため、ラムダがまったく必要ない場合もあります。デフォルトの並べ替えと大文字と小文字を区別しない並べ替えを比較します。
names = ["Asha", "ben", "Chitra", "dev"]
sorted(names) # ['Asha', 'Chitra', 'ben', 'dev']
sorted(names, key=str.lower) # ['Asha', 'ben', 'Chitra', 'dev']
デフォルトでは、すべての大文字の単語が最初に配置されます。 str.lower を渡すと、ラムダなしで問題が修正されます。 operator モジュールは、lambda p: p[1] の itemgetter(1) など、同様のヘルパーを提供します。
マップとフィルター
map はすべての項目に関数を適用し、filter は true を返す項目を保持します。どちらもラムダで動作しますが、それぞれをリスト内包表記で比較します。
nums = [1, 2, 3, 4, 5, 6]
list(map(lambda n: n * 10, nums)) # [10, 20, 30, 40, 50, 60]
[n * 10 for n in nums] # [10, 20, 30, 40, 50, 60]
list(filter(lambda n: n % 2 == 0, nums)) # [2, 4, 6]
[n for n in nums if n % 2 == 0] # [2, 4, 6]
結果は同じであり、ほとんどの Python 開発者は内包表記が読みやすいと感じています。 map と filter は遅延反復子を返すため、値を確認するには list() が必要であることにも注意してください。 Python リスト理解 のガイドでは、そのスタイルについて詳しく説明しています。 map は、map(str.strip, lines) と同様に、既存の名前付き関数でも適切に読み取れます。
減らす
functools.reduce 項目を単一の値に結合し、実行結果を伝えます。
from functools import reduce
reduce(lambda acc, n: acc + n, nums, 0) # 21
sum(nums) # 21
合計などの一般的なジョブの場合は、sum、max、any などの組み込みを使用します。まれなケースに備えて reduce を保持し、ラムダが複雑に見え始めた場合は単純なループを検討してください。
ラムダ内の条件
ラムダでは if ステートメントを使用できませんが、条件式は使用できます。
label = lambda total: "large" if total >= 1000 else "small"
label(1200), label(300)
# ('large', 'small')
条件は一つでも大丈夫です。それらをネストし始めると、読者は懸命に働かなければなりません。これは、通常の if ステートメントを def に切り替える明らかな兆候です。
関数を返すラムダ
関数は、周囲の値を記憶するラムダを作成して返すことができます。
def multiplier(n):
return lambda x: x * n
double = multiplier(2)
double(7) # 14
これはクロージャのおかげで機能します。JavaScript クロージャに関する記事で別の言語で説明されています。 Python の functools.partial は、引数を事前に入力する別の方法を提供します。
遅延バインディングの罠
これは最終的にほぼ全員に影響を及ぼします。ループ内に 3 つのラムダを作成し、それぞれが独自の番号を返すことを期待しました。
funcs = [lambda: i for i in range(3)]
[f() for f in funcs]
# [2, 2, 2]
3 つすべて 2 を返します。ラムダは、作成時に i の 値 をキャプチャしません。 呼び出されるときに変数を検索し、その時点でループは終了し、iは 2 のままになります。デフォルトは定義時に評価されるため、通常の修正方法は、値をデフォルトの引数としてキャプチャすることです。
funcs = [lambda i=i: i for i in range(3)]
[f() for f in funcs]
# [0, 1, 2]
ループ内の def も同様に動作するため、これはラムダに特有のものではありません。ボタンのコールバックをアタッチするときなど、ラムダはループ内で作成されるのが一般的であるため、ラムダの場合によく現れます。
ヒント: アイテムごとに関数が必要な場合は、そもそも多くの関数が必要かどうかを検討してください。多くの場合、項目を引数として受け取る単一関数の方が明確であり、トラップを完全に回避します。
小さな関数のルックアップ テーブル
ラムダは、名前を小さな操作にマッピングする辞書にきちんと収まります。
ops = {
"add": lambda a, b: a + b,
"sub": lambda a, b: a - b,
}
ops["sub"](10, 3) # 7
これは、if と elif の長いチェーンを置き換えることができます。 Python 辞書 ガイドではさらに多くの辞書パターンがカバーされており、operator モジュールではすでに operator.add と operator.sub が提供されています。
ラムダの限界
- 式は 1 つだけ。
=、ループ、tryブロックによる代入はありません。 - ステートメントがありません。 テストで確認されたように、
lambda x: return xを書くとSyntaxErrorで失敗します。 - ドキュメント文字列や入力ヒントはありません。 ツールとリーダーのサポートが少なくなります。
- デバッグが難しくなります。 エラーは役立つ名前ではなく
<lambda>を指します。
もちろん、ラムダは引き続き例外を発生させることができます。これらの処理は、Python 例外処理 で説明されているように、他の関数と同様に機能します。
ラムダを使用しない場合
| 状況 | より良い選択 |
|---|---|
| 名前を付ける | 確かに |
| ロジックには複数の行が必要です | 確かに |
| リストの変換またはフィルタリング | リストの内包表記 |
| 合計または最大値を求める | sum、max、min |
| アイテムまたは属性の取得 | operator.itemgetterまたはattrgetter |
| 同じラムダが複数の場所に出現する | テストできる名前付き関数 |
最後の点が重要です。 pytest チュートリアル が示すように、再利用する価値のあるロジックはテストする価値があり、名前付き関数の方がテストがはるかに簡単です。
まとめ
優れたラムダは一目で読めるほど短く、通常は引数として 1 回使用されます。ソートキーはその典型的な例です。独自のコードを確認するには、= lambda を検索し、それらを名前付き関数に変換します。次に、map または filter をラムダで調べて、理解がより適切になるかどうかを確認します。
よくある質問
Python のラムダ関数とは何ですか?
これは、lambda キーワードを使用して作成された小さな匿名関数です。これは引数を受け取り、名前や return ステートメントなしで 1 つの式の値を返します。
Python ラムダには複数の行を含めることはできますか?
いいえ。ラムダは 1 つの式に限定されます。括弧内で複数の行に分割できますが、ステートメントを含めることはできないため、より複雑なロジックには def を使用します。
ラムダで if else を使用できますか?
lambda x: “big” if x > 10 else “small” などの条件式を使用できます。ブロックを含む if ステートメントは許可されません。
ラムダは通常の関数より高速ですか?
意味のあることではありません。どちらも同じ種類の関数オブジェクトを作成します。パフォーマンスではなく、読みやすさを重視してどちらかを選択してください。
ラムダ付きマップまたはリスト内包表記を使用する必要がありますか?
ほとんどの Python 開発者は、読みやすさを考慮してリスト内包表記を好みます。 map(str.strip, Lines) などの名前付き関数がすでにある場合は、map が適切です。
学び続ける
テスト、WordPress、または SEO についてサポートが必要ですか?
私たちは、チームがより優れたソフトウェアを出荷し、サイトを成長させるのを支援します。あなたが取り組んでいることを教えてください。明確な次のステップを提案します。
詳しいガイドはこちら テスト、AI、最新の開発
この記事は気に入りましたか?トピックを選択して、最新のチュートリアルに直接アクセスしてください。
AI 幻覚の説明: 言語モデルが物事をでっち上げる理由とそれを軽減する方法
AI 幻覚について説明しました。幻覚とは何か、言語モデルが幻覚を生成する理由、一般的な種類、グラウンディングとプロンプトで幻覚を軽減する方法、そして私たちが実行した簡単なチェックです。
記事を読む →DevOps環境変数の説明: .env ファイル、シークレット、および設定が正しく行われている
実行した Python の例を使用して環境変数について説明します。環境変数の読み取りと設定、すべての値が文字列である理由、.env ファイル、プロセスの継承、シークレット、検証について説明します。
記事を読む →ソフトウェア開発API レート制限の説明: アルゴリズム、ヘッダー、および 429 エラーの処理
API レート制限については、実行したシミュレーションで説明します。トークン バケット、固定ウィンドウ、スライディング ウィンドウ、429 応答、レート制限ヘッダー、バックオフによる再試行、およびテスト制限です。
記事を読む →テスト自動化Python でのモッキング:unittest.mock、patch、およびテストを嘘にする間違い
Python でのunittest.mockによるモック、テスト済み: モックとreturn_value、side_effect、名前が使用されている場所のパッチ、仕様と自動仕様、日付のモック、およびよくある間違い。
記事を読む →ソフトウェアテストコードカバレッジの説明: 回線カバレッジとブランチカバレッジ、および 100% の実際の意味
実際のcoverage.pyの実行でコードカバレッジを説明: 行、分岐、条件のカバレッジ、レポートの読み取り、100%のカバレッジでもバグを見逃す可能性がある理由、および賢明なターゲット。
記事を読む →データベースとSQLSQL における DELETE、TRUNCATE、DROP: 違い、ロールバック、およびそれぞれをいつ使用するか
DELETE、TRUNCATE、DROP について、テスト済み SQL を使用して説明します。それぞれの削除内容、ロールバック、トリガー、ID リセット、速度、PostgreSQL、MySQL、SQL Server、SQLite の違いについて説明します。
記事を読む →データベースとSQLSQL ビューの説明: 作成、使用、落とし穴の回避、例を示します
SQL ビューについて、実行したクエリとともに説明しました。ビューの作成、ライブ結果、列の非表示、パフォーマンス、更新可能なビューと具体化されたビュー、壊れた依存関係、ベスト プラクティスについて説明します。
記事を読む →ソフトウェア開発TypeScript インターフェイスと型: 実際の違い、コンパイラでテスト
TypeScript インターフェイスと型、実際のコンパイラでチェック: 両方でできること、片方だけでできること、宣言のマージ、拡張と交差、および従うべき簡単なルール。
記事を読む →ソフトウェア開発Python *args と **kwargs の説明: 柔軟な関数と明確な例
Python の *args と **kwargs について、実行したコードで説明しました。パッキングとアンパッキング、パラメーターの順序、キーワードのみの引数と位置のみの引数、デコレーター、一般的なエラーです。
記事を読む →ソフトウェア開発Python Lambda 関数: 構文、実際の用途、および使用すべきでない場合
Python のラムダ関数について、実行したコードとともに説明します。構文、キーによるソート、マップとフィルター、クロージャー、遅延バインディング トラップ、通常の def がより適切な選択である場合。
記事を読む →人工知能AIエージェントとは何ですか?シンプルなエージェント ループを実行できる仕組み
AIエージェントとは何ですか?エージェント ループ、ツール、メモリ、ガードレール、実行した小さな Python ループ、実際のリスク、およびシンプルなチャットボットがより良い選択である場合についてのわかりやすいガイドです。
記事を読む →DevOpsモニタリングと可観測性: ログ、メトリクス、トレースによる本当の違い
モニタリングと可観測性について説明: 既知および未知の障害、ログ、メトリクスとトレース、チェックアウト インシデントのウォークスルー、ゴールデン シグナル、OpenTelemetry、および便利なアラート。
記事を読む →DevOpsDocker ボリュームとバインド マウント: コンテナ データを正しい方法で保持する
Docker ボリュームとバインド マウントについて説明します。コンテナ データが消える理由、名前付きボリューム、バインド マウント、tmpfs、Compose の例、バックアップ、アクセス許可、およびそれぞれをいつ使用するかについて説明します。
記事を読む →テスト自動化TDD と BDD: 主な違い、1 つの機能が両方の方法で構築され、それぞれをいつ使用するか
TDD と BDD は、両方の方法で構築された 1 つの割引機能で説明されています。実行したコードによるレッド-グリーン-リファクタリング、Given-When-Then シナリオ、ツール、トレードオフ、およびそれぞれをいつ使用するかです。
記事を読む →ソフトウェア開発Git mergeとrebaseの違い:例と使い分け
Git mergeとrebaseの違いを、実際のログ出力、比較表、rebaseの黄金律、安全なチームワークフローで解説します。
記事を読む →ソフトウェア開発Pythonのリスト内包表記:構文・例・使うべきでない場面
Pythonのリスト内包表記を解説:構文、フィルタ、if-else、ネストしたループ、実測した処理時間、そして通常のforループの方が良い場面。
記事を読む →データベースとSQLSQL JOINを例で解説(Inner・Left・Right・Full)
サンプルのテーブルとクエリでSQL JOINを順に解説。INNER、LEFT、RIGHT、FULL、CROSS、SELFに加え、よくある間違いとパフォーマンスのコツも紹介します。
記事を読む →