ProgrammingPython開発者

Pythonにおけるラムダ関数について説明してください。それに対する一般的な関数との制約は何ですか?どのような状況でラムダを使用することが好ましいか、またどのような場合に避けるべきですか?

Hintsage AIアシスタントで面接を突破

回答

ラムダ関数は、lambdaキーワードを使って定義される匿名(名前のない)関数です。通常は、"一度だけ、場所で"短い関数が必要な場合に使用されます。

add = lambda x, y: x + y print(add(1, 2)) # 3

ラムダ関数の制約:

  • ラムダは単一の式のみを含むことができ、戻り値になります。複数行の計算、return、if-elseのような条件(のみ三項演算子として)を行うことはできません。
  • try/except、ループなどの複雑なコードを使用することはできません。
  • ラムダには十分なドキュメントがありません(docstringを追加することができません)。
  • ラムダ関数は特にネストされると読みづらくなります。

ラムダを使用するのに便利な場合:

  • 単一行のソート/フィルタリングのキー(key引数; 例として、sortedfiltermapで)。
  • コードの再利用が必要ない場合 — ローカル操作、関数をすぐに"置き換える"ため。

ラムダを避けるべき場合:

  • 複雑なロジックの場合:再利用のために、コードや条件が多い場合、可読性や理解を優先するためにdef関数に名前とドクストリングを付けて取り出す方が良いです。

ひねりのある質問

質問: ラムダ関数は外部スコープの変数を使用できますか、そしてそれはループ内での動作にどのように影響しますか?

回答: ラムダ関数は外部コンテキスト(レキシカルスコーピング)から変数をキャプチャすることができます。ループ内に定義すると、これはしばしば予期しない動作を引き起こします — ラムダは呼び出し時の変数の現在の値を使用し、"定義時の値"ではありません。

funcs = [] for i in range(3): funcs.append(lambda: i) # すべての関数は2を返します(ループ後、i=2) print([f() for f in funcs]) # [2, 2, 2]

"古い"値をキャプチャするには:

funcs = [] for i in range(3): funcs.append(lambda i=i: i) print([f() for f in funcs]) # [0, 1, 2]

このテーマの知識不足から生じた実際のエラーの例


物語

プロジェクトでは、特定のキーに基づいて辞書のリストをフィルタリングするためにラムダを使用しました。ループ内のラムダは、呼び出し時に異なる(予期しない)値を持つ変数をキャプチャしました。結果 — 不適切なフィルタリングと報告のエラー。


物語

大規模なDjangoプロジェクト:ラムダ関数内の長い式として実装された複雑なバリデーションフォーム。その後ビジネスロジックが変更され、ラムダはすべてのコードを収納できなくなり、通常の関数に書き直す必要がありました。ラムダによりデバッグが遅れました。


物語

あるスタートアップでは、ソート関数を渡すためのラムダを不適切に使用し、戻り値が正しい型でないことを忘れました(たとえば、タプルではなくリスト)。これにより、予測できないソート結果とデータの重複排除に関するバグが発生しました。