Python Lambda関数の使用方法

Python Lambda関数の使用方法

PythonおよびJava、C#、さらにC ++などの他の言語では、構文にラムダ関数が追加されていますが、LISPやMLファミリの言語、Haskell、OCaml、F#などの言語では、ラムダをコアコンセプトとして使用しています。

Pythonラムダは、小さな匿名関数であり、通常のPython関数よりも制限的ではありますが簡潔な構文に従います。

この記事の終わりまでに、次のことがわかります:

  • Pythonラムダがどのようになったか

  • ラムダと通常の関数オブジェクトとの比較

  • ラムダ関数の書き方

  • Python標準ライブラリのどの関数がラムダを活用しているか

  • Pythonラムダ関数を使用または回避する場合

:Pythonスタイルのベストプラクティスを露骨に無視しているように見える `+ lambda `を使用したコード例があります。 これは、ラムダ計算の概念を説明するか、Python ` lambda +`の機能を強調することのみを目的としています。

これらの疑わしい例は、記事を進めるにつれて、より良いアプローチや代替案と対比されます。

このチュートリアルは、主に中級から上級のPythonプログラマーを対象としていますが、プログラミングやラムダ計算に興味がある好奇心to盛な人であれば誰でもアクセスできます。

このチュートリアルに含まれるすべての例は、Python 3.7でテストされています。

  • __クイズに挑戦:*インタラクティブな「Python Lambda関数」クイズで知識をテストします。 完了すると、学習の進捗状況を経時的に追跡できるようにスコアを受け取ります。

link:/quizzes/python-lambda/[クイズに挑戦»]

*無料ボーナス:*リンク:[Python Tricks:The Book]の章にアクセスするには、ここをクリックして、Pythonのベストプラクティスを簡単な例とともに示します。すぐに適用して、より美しい+ Pythonコードを記述できます。

ラムダ計算

Pythonおよび他のプログラミング言語のラムダ式は、Alonzo Churchによって発明された計算モデルであるラムダ計算にルーツがあります。 ラムダ計算が導入された時期と、それがPythonエコシステムで最終的に採用された基本概念である理由を明らかにします。

歴史

Alonzo Churchは、1930年代に純粋な抽象化に基づいた言語であるhttps://en.wikipedia.org/wiki/Lambda_calculus[lambda calculus]を正式化しました。 ラムダ関数は、ラムダ抽象化とも呼ばれ、アロンゾ教会の創作の抽象化モデルへの直接の参照です。

ラムダ計算は任意の計算をエンコードできます。 Turing completeですが、https://en.wikipedia.org/wiki/Turing_machine [Turing machine]の概念に反して、純粋でありません状態を保持しません。

関数型言語は数学的論理とラムダ計算に起源を持ち、命令型プログラミング言語はアランチューリングが発明した状態ベースの計算モデルを採用しています。 計算の2つのモデル、ラムダ計算とhttps://en.wikipedia.org/wiki/Turing_machine[Turing machine]は、相互に変換できます。 この等価性は、https://en.wikipedia.org/wiki/Church%E2%80%93Turing_thesis [Church-Turing仮説]として知られています。

関数型言語は、ラムダ計算の哲学を直接継承し、抽象化、データ変換、構成、および純度(状態および副作用なし)を重視する宣言型のプログラミングアプローチを採用しています。 機能言語の例には、https://www.haskell.org/[Haskell]、https://en.wikipedia.org/wiki/Lisp_%28programming_language%29 [Lisp]、またはhttps://www.erlang.orgが含まれます。/[Erlang]。

対照的に、チューリングマシンはhttps://en.wikipedia.org/wiki/Fortran[Fortran]、https://en.wikipedia.org/wiki/C_%28programming_language%29[C ]、またはhttps://www.python.org/[Python]。

命令型スタイルは、ステートメントを使用したプログラミングで構成され、プログラムのフローを詳細な手順で段階的に駆動します。 このアプローチは突然変異を促進し、状態を管理する必要があります。

いくつかの関数型言語はhttp://www.ocaml.org/[OCaml]などの命令型機能を組み込んでいるため、両方のファミリでの分離にはいくつかのニュアンスがありますが、特にラムダの導入により関数型関数は命令型の言語ファミリに浸透していますhttps://en.wikipedia.org/wiki/Java_%28programming_language%29[Java]またはPythonの関数。

Pythonは本質的に関数型言語ではありませんが、早い段階でいくつかの関数型の概念を採用しました。 1994年1月、 + map()++ filter()++ reduce()+、および `+ lambda +`演算子が言語に追加されました。

最初の例

ここに、Pythonコードの機能的なスタイルに対する欲求を与えるいくつかの例を示します。

引数を返す関数であるhttps://en.wikipedia.org/wiki/Identity_function[identity function]は、次のようにキーワード `+ def +`を使用して標準のPython関数定義で表現されます。

>>>

>>> def identity(x):
...     return x

`+ identity()`は引数 ` x +`を取り、呼び出し時にそれを返します。

対照的に、Pythonラムダ構造を使用すると、次の結果が得られます。

>>>

>>> lambda x: x

上記の例では、式は次のもので構成されています。

  • キーワード: + lambda +

  • バインドされた変数: + x +

  • 本体: + x +

:この記事のコンテキストでは、*バインド変数*はラムダ関数の引数です。

対照的に、* free変数*はバインドされておらず、式の本文で参照できます。 自由変数は、定数または関数の囲みスコープで定義された変数です。

次のように、引数に「1」を追加する関数である、もう少し複雑な例を作成できます。

>>>

>>> lambda x: x + 1

関数とその引数を括弧で囲むことにより、上記の関数を引数に適用できます。

>>>

>>> (lambda x: x + 1)(2)
3

Reductionは、式の値を計算するためのラムダ計算戦略です。 これは、引数「2」を「+ x +」に置き換えることで構成されます。

(lambda x: x + 1)(2) = lambda 2: 2 + 1
                     = 2 + 1
                     = 3

ラムダ関数は式であるため、名前を付けることができます。 したがって、次のように以前のコードを書くことができます。

>>>

>>> add_one = lambda x: x + 1
>>> add_one(2)
3

上記のラムダ関数は、これを書くのと同等です。

def add_one(x):
    return x + 1

これらの関数はすべて単一の引数を取ります。 お気付きかもしれませんが、ラムダの定義では、引数の周りに括弧がありません。 マルチ引数関数(複数の引数を取る関数)は、引数をリストし、それらを括弧で囲まずにコンマ( )で区切ることにより、Pythonラムダで表現されます。

>>>

>>> full_name = lambda first, last: f'Full name: {first.title()} {last.title()}'
>>> full_name('guido', 'van rossum')
'Full name: Guido Van Rossum'

`+ full_name `に割り当てられたラムダ関数は2つの引数を取り、2つのパラメーター ` first `と ` last +`を補間する文字列を返します。 予想どおり、ラムダの定義は括弧なしで引数をリストしますが、関数の呼び出しは通常のPython関数とまったく同じように行われ、引数を括弧で囲みます。

無名関数

次の用語は、プログラミング言語の種類と文化に応じて交換可能に使用される場合があります。

  • 無名関数

  • ラムダ関数

  • ラムダ式

  • ラムダ抽象化

  • ラムダ形

  • 関数リテラル

このセクションの後のこの記事の残りの部分では、ほとんどの場合、「ラムダ関数」という用語が表示されます。

文字通り、匿名関数は名前のない関数です。 Pythonでは、 `+ lambda `キーワードを使用して匿名関数が作成されます。 さらに大まかに言うと、名前が割り当てられている場合と割り当てられていない場合があります。 ` lambda +`で定義されているが変数にバインドされていない2引数の匿名関数を考えてみましょう。 ラムダには名前が付けられていません:

>>>

>>> lambda x, y: x + y

上記の関数は、2つの引数を取り、それらの合計を返すラムダ式を定義します。

Pythonがこのフォームで完全に問題ないというフィードバックを提供する以外は、実用化にはつながりません。 Pythonインタープリターで関数を呼び出すことができます。

>>>

>>> _(1, 2)
3

上記の例は、アンダースコア( + _ +)を介して提供されるインタラクティブなインタープリターのみの機能を利用しています。 詳細については、以下の注を参照してください。

Pythonモジュールで同様のコードを書くことはできませんでした。 インタープリターの「+ _ +」を利用した副作用として考えてください。 Pythonモジュールでは、ラムダに名前を割り当てるか、ラムダを関数に渡します。 この2つのアプローチは、この記事の後半で使用します。

:インタラクティブインタープリターでは、単一の下線( + _ +)が最後に評価された式にバインドされます。

上記の例では、 `+ _ +`はラムダ関数を指します。 Pythonでのこの特殊文字の使用に関する詳細については、https://dbader.org/blog/meaning-of-underscores-in-python [Pythonでのアンダースコアの意味]をご覧ください。

JavaScriptなどの他の言語で使用される別のパターンは、Pythonラムダ関数をすぐに実行することです。 これは Immediately Invoked Function Expression (https://developer.mozilla.org/en-US/docs/Glossary/IIFE[IIFE]、「iffy」と発音)として知られています。 例を示しましょう。

>>>

>>> (lambda x, y: x + y)(2, 3)
5

上記のラムダ関数が定義され、すぐに2つの引数( + 2 +`と `+ 3 +)で呼び出されます。 引数の合計である値「5」を返します。

このチュートリアルのいくつかの例では、この形式を使用してラムダ関数の匿名の側面を強調し、Pythonで関数を定義する短い方法として「+ lambda +」に焦点を当てないようにします。

Pythonは、すぐに呼び出されるラムダ式の使用を推奨していません。 通常の関数の本体とは異なり、単にラムダ式が呼び出し可能になった結果です。

Lambda関数は、https://en.wikipedia.org/wiki/Higher-order_function [higher-order functions]で頻繁に使用され、1つ以上の関数を引数として受け取るか、1つ以上の関数を返します。

ラムダ関数は、次の不自然な例のように関数(通常またはラムダ)を引数として使用することにより、高次関数になります。

>>>

>>> high_ord_func = lambda x, func: x + func(x)
>>> high_ord_func(2, lambda x: x * x)
6
>>> high_ord_func(2, lambda x: x + 3)
7

Pythonは、高階関数を組み込み関数として、または標準ライブラリで公開します。 例には、「+ map()」、「 filter()」、「 functools.reduce()」、および「 sort()」、「 sorted()」などのキー関数、 ` min()`、および ` max()+`。 link:#appropriate-uses-of-lambda-expressions [Lambda Expressionsの適切な使用]で、ラムダ関数とPython高次関数を使用します。

Python Lambdaと通常の関数

Python Design and History FAQからのこの引用は、Pythonでのラムダ関数の使用に関する全体的な期待についてのトーンを設定しているようです。

_ 機能を追加する他の言語のラムダフォームとは異なり、Pythonラムダは、関数を定義するのが面倒な場合の略記法にすぎません。 (https://docs.python.org/3/faq/design.html#why-can-t-lambda-expressions-contain-statements [ソース]) _

それでも、このステートメントがPythonの `+ lambda +`の使用を妨げないようにしてください。 一見すると、ラムダ関数はhttps://en.wikipedia.org/wiki/Syntactic_sugar[syntactic_sugar]でコードを短縮して関数を定義または呼び出す関数です。 次のセクションでは、通常のPython関数とラムダ関数の共通点と微妙な違いを強調します。

関数

この時点で、変数にバインドされたラムダ関数と、「+ return 」行が1本だけの通常の関数とを根本的に区別するものは何なのか疑問に思うかもしれません。 Pythonが単一のreturnステートメントで構築された関数と式( ` lambda +`)として構築された関数をどのように認識するかを確認しましょう。

https://docs.python.org/3/library/dis.html [+ dis +]モジュールは、Pythonコンパイラーによって生成されたPythonバイトコードを分析する関数を公開します。

>>>

>>> import dis
>>> add = lambda x, y: x + y
>>> type(add)
<class 'function'>
>>> dis.dis(add)
  1           0 LOAD_FAST                0 (x)
              2 LOAD_FAST                1 (y)
              4 BINARY_ADD
              6 RETURN_VALUE
>>> add
<function <lambda> at 0x7f30c6ce9ea0>

`+ dis()+`がPythonバイトコードの読み取り可能なバージョンを公開し、Pythonインタープリターがプログラムの実行中に使用する低レベルの命令を検査できることがわかります。

今、通常の関数オブジェクトでそれを見てください:

>>>

>>> import dis
>>> def add(x, y): return x + y
>>> type(add)
<class 'function'>
>>> dis.dis(add)
  1           0 LOAD_FAST                0 (x)
              2 LOAD_FAST                1 (y)
              4 BINARY_ADD
              6 RETURN_VALUE
>>> add
<function add at 0x7f30c6ce9f28>

Pythonによって解釈されるバイトコードは、両方の関数で同じです。 しかし、名前が異なることに気付くかもしれません:関数名は `+ def `で定義された関数の ` add `ですが、Pythonラムダ関数は ` lambda +`と見なされます。

トレースバック

前のセクションで、ラムダ関数のコンテキストでは、Pythonは関数の名前を提供せず、 `+ <lambda> `のみを提供することを見ました。 これは、例外がいつ発生するかを考慮するための制限であり、トレースバックは ` <lambda> +`のみを表示します。

>>>

>>> div_zero = lambda x: x/0
>>> div_zero(2)
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 1, in <lambda>
ZeroDivisionError: division by zero

ラムダ関数の実行中に発生した例外のトレースバックは、例外の原因となっている関数を `+ <lambda> +`として識別するだけです。

通常の関数で発生する同じ例外は次のとおりです。

>>>

>>> def div_zero(x): return x/0
>>> div_zero(2)
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 1, in div_zero
ZeroDivisionError: division by zero

通常の関数でも同様のエラーが発生しますが、関数名 `+ div_zero +`が付与されるため、より正確なトレースバックが発生します。

構文

前のセクションで見たように、ラムダ形式は通常の関数との構文上の違いを示します。 特に、ラムダ関数には次の特性があります。

  • 式のみを含めることができ、本文にステートメントを含めることはできません。

  • 1行の実行として記述されます。

  • 型注釈はサポートしていません。

  • すぐに呼び出すことができます(IIFE)。

文なし

ラムダ関数にステートメントを含めることはできません。 ラムダ関数では、「+ return 」、「 pass 」、「 assert 」、または「 raise 」などのステートメントは、「 SyntaxError 」例外を発生させます。 以下に、ラムダの本体に「 assert +」を追加する例を示します。

>>>

>>> (lambda x: assert x == 2)(2)
  File "<input>", line 1
    (lambda x: assert x == 2)(2)
                    ^
SyntaxError: invalid syntax

この考案された例は、パラメータ「+ x 」の値が「+2」であるという「+ assert 」を意図しています。 しかし、インタープリターは、 ` lambda `の本体にステートメント ` assert `を含むコードを解析しているときに、 ` SyntaxError +`を識別します。

単一表現

通常の関数とは対照的に、Pythonラムダ関数は単一の式です。 `+ lambda +`の本文では、括弧または複数行の文字列を使用して式を複数の行に広げることができますが、単一の式のままです:

>>>

>>> (lambda x:
... (x % 2 and 'odd' or 'even'))(3)
'odd'

上記の例は、ラムダ引数が奇数の場合は文字列「+ 'odd' 」を返し、引数が偶数の場合は「 'even' +」を返します。 括弧のセットに含まれているため、2行に広がりますが、単一の式のままです。

タイプ注釈

Pythonで利用できるようになったタイプヒンティングの採用を開始した場合、Pythonラムダ関数よりも通常の関数を好むもう1つの理由があります。 Python Type Checking(Guide)をチェックして、Pythonのタイプヒントとタイプチェックの詳細を確認してください。 ラムダ関数では、次のものに相当するものはありません。

def full_name(first: str, last: str) -> str:
    return f'{first.title()} {last.title()}'

+ full_name()+`の型エラーは、http://mypy-lang.org/[+ mypy `]やhttps://pyre-check.org/[` pyre `]などのツールでキャッチできます。 、同等のラムダ関数を持つ ` SyntaxError +`が実行時に発生します:

>>>

>>> lambda first: str, last: str: first.title() + " " + last.title() -> str
  File "<stdin>", line 1
    lambda first: str, last: str: first.title() + " " + last.title() -> str

SyntaxError: invalid syntax

ステートメントをラムダに含めようとすると、型注釈を追加すると、実行時にすぐに `+ SyntaxError +`が発生します。

*IIFE*

https://developer.mozilla.org/en-US/docs/Glossary/IIFE [すぐに呼び出される関数の実行]の例をいくつか見てきました。

>>>

>>> (lambda x: x * x)(3)
9

Pythonインタープリター以外では、この機能はおそらく実際には使用されません。 定義されたとおりにラムダ関数が呼び出し可能であることの直接的な結果です。 たとえば、これにより、Pythonラムダ式の定義を + map()++ filter()+、または `+ functools.reduce()+`などの高次関数に渡すことができます。または、キー機能に。

引数

`+ def +`で定義された通常の関数オブジェクトのように、Pythonラムダ式は引数を渡すさまざまな方法をすべてサポートしています。 これも:

  • 位置引数

  • 名前付き引数(キーワード引数とも呼ばれます)

  • 引数の変数リスト( varargs と呼ばれることが多い)

  • キーワード引数の変数リスト *キーワードのみの引数

次の例は、ラムダ式に引数を渡すために利用できるオプションを示しています。

>>>

>>> (lambda x, y, z: x + y + z)(1, 2, 3)
6
>>> (lambda x, y, z=3: x + y + z)(1, 2)
6
>>> (lambda x, y, z=3: x + y + z)(1, y=2)
6
>>> (lambda* args: sum(args))(1,2,3)
6
>>> (lambda **kwargs: sum(kwargs.values()))(one=1, two=2, three=3)
6
>>> (lambda x, *, y=0, z=0: x + y + z)(1, y=2, z=3)
6

デコレータ

Pythonでは、https://www.python.org/dev/peps/pep-0318/[decorator]は、関数またはクラスに動作を追加できるパターンの実装です。 通常、関数の前に `+ @ decorator +`構文を付けて表現します。 これが不自然な例です。

def some_decorator(f):
    def wraps(*args):
        print(f"Calling function '{f.__name__}'")
        return f(args)
    return wraps

@some_decorator
def decorated_function(x):
    print(f"With argument '{x}'")

上記の例では、 `+ some_decorator()`は ` decorated_function()`に動作を追加する関数であるため、 ` decorated_function(" Python ")+`を呼び出すと次の出力が得られます。

Calling function 'decorated_function'
With argument 'Python'

`+ decorated_function()`は ` With引数 'Python' `のみを出力しますが、デコレーターは ` Calling function 'decorated_function' +`も出力する追加の動作を追加します。

デコレータはラムダに適用できます。 `+ @ decorator +`構文を使用してラムダを修飾することはできませんが、デコレータは単なる関数であるため、ラムダ関数を呼び出すことができます。

 1 # Defining a decorator
 2 def trace(f):
 3     def wrap(*args, **kwargs):
 4         print(f"[TRACE] func: {f.__name__}, args: {args}, kwargs: {kwargs}")
 5         return f(*args, **kwargs)
 6
 7     return wrap
 8
 9 # Applying decorator to a function
10 @trace
11 def add_two(x):
12     return x + 2
13
14 # Calling the decorated function
15 add_two(3)
16
17 # Applying decorator to a lambda
18 print((trace(lambda x: x ** 2))(3))

11行目で `+ @ trace `で装飾された ` add_two()`は、15行目で引数 ` 3 `で呼び出されます。 対照的に、18行目では、ラムダ関数がデコレータである ` trace()+`の呼び出しに直ちに組み込まれ、埋め込まれています。 上記のコードを実行すると、次のものが得られます。

[TRACE] func: add_two, args: (3,), kwargs: {}
[TRACE] func: <lambda>, args: (3,), kwargs: {}
9

すでに見たように、ラムダ関数の名前が「+ <lambda> 」として表示されるのに対し、通常の関数では「 add_two +」が明確に識別されます。

ラムダ関数をこのように装飾することは、デバッグの目的で、おそらく高階関数またはキー関数のコンテキストで使用されるラムダ関数の動作をデバッグするのに役立ちます。 `+ map()+`の例を見てみましょう:

list(map(trace(lambda x: x*2), range(3)))

`+ map()`の最初の引数は、その引数に ` 2 `を掛けるラムダです。 このラムダは ` trace()+`で装飾されています。 実行すると、上記の例は次を出力します。

[TRACE] Calling <lambda> with args (0,) and kwargs {}
[TRACE] Calling <lambda> with args (1,) and kwargs {}
[TRACE] Calling <lambda> with args (2,) and kwargs {}
[0, 2, 4]

結果の「+ [0、2、4] 」は、「 range(3)」の各要素を乗算したリストです。 今のところ、リスト ` [0、1、2] `と同等の ` range(3)+`を検討してください。

link:#map [Map]でより詳細に `+ map()+`にさらされます。

ラムダもデコレータにすることができますが、推奨されません。 これを行う必要がある場合は、https://www.python.org/dev/peps/pep-0008/#programming-recommendations [PEP 8、プログラミングの推奨事項]を参照してください。

Pythonデコレーターの詳細については、https://realpython.com/primer-on-python-decorators/[Primer on Python Decorators]をご覧ください。

閉鎖

closureは、その関数で使用されるすべての自由変数(パラメーターを除くすべて)が、その囲みスコープで定義された特定の値にバインドされる関数です関数。 実際には、クロージャーは実行する環境を定義するため、どこからでも呼び出すことができます。

ラムダ関数とクロージャーの概念は必ずしも関連しているわけではありませんが、ラムダ関数は通常の関数もクロージャーと同じようにクロージャーにすることができます。 一部の言語には、クロージャーまたはラムダ(クロージャーオブジェクトとしてコードの匿名ブロックを使用するGroovyなど)、またはラムダ式(クロージャーのオプションが制限されているJava Lambda式など)の特別な構造があります。

通常のPython関数で構築されたクロージャーは次のとおりです。

 1 def outer_func(x):
 2     y = 4
 3     def inner_func(z):
 4         print(f"x = {x}, y = {y}, z = {z}")
 5         return x + y + z
 6     return inner_func
 7
 8 for i in range(3):
 9     closure = outer_func(i)
10     print(f"closure({i+5}) = {closure(i+5)}")

`+ outer_func()`は、3つの引数の合計を計算する入れ子関数である ` inner_func()+`を返します。

  • + x + は引数として `+ outer_func()+`に渡されます。

  • + y + は、 `+ outer_func()+`のローカル変数です。

  • + z + は、 `+ inner_func()+`に渡される引数です。

`+ outer_func()`および ` inner_func()`の動作をテストするために、以下を出力する ` for `ループで ` outer_func()+`が3回呼び出されます。

x = 0, y = 4, z = 5
closure(5) = 9
x = 1, y = 4, z = 6
closure(6) = 11
x = 2, y = 4, z = 7
closure(7) = 13

コードの9行目で、 + outer_func()+`の呼び出しによって返される `+ inner_func()+`は、名前 `+ closure +`にバインドされます。 5行目では、 `+ inner_func()+`は、埋め込み環境にアクセスできるため、 `+ x +`と `+ y +`をキャプチャします。クロージャの呼び出し時に、2つの自由変数 `+ x + `および + y + `。

同様に、 `+ lambda +`もクロージャにすることができます。 Pythonラムダ関数を使用した同じ例:

 1 def outer_func(x):
 2     y = 4
 3     return lambda z: x + y + z
 4
 5 for i in range(3):
 6     closure = outer_func(i)
 7     print(f"closure({i+5}) = {closure(i+5)}")

上記のコードを実行すると、次の出力が得られます。

closure(5) = 9
closure(6) = 11
closure(7) = 13

6行目では、 `+ outer_func()`はラムダを返し、それを変数 ` closure `に割り当てます。 3行目では、ラムダ関数の本体が ` x `と ` y `を参照しています。 変数「 y 」は定義時に使用できますが、「 x 」は「 outer_func()+」が呼び出されたときに実行時に定義されます。

この状況では、通常の関数とラムダの両方が同様に動作します。 次のセクションでは、ラムダの動作が評価時間(定義時間と実行時間)により誤解を招く可能性がある状況を確認します。

評価時間

loopsを含むいくつかの状況では、クロージャーとしてのPythonラムダ関数の動作は直感に反する場合があります。 ラムダのコンテキストで自由変数がバインドされるタイミングを理解する必要があります。 次の例は、通常の関数を使用する場合とPythonラムダを使用する場合の違いを示しています。

通常の機能を使用して最初にシナリオをテストします。

>>>

 1 >>> def wrap(n):
 2 ...     def f():
 3 ...         print(n)
 4 ...     return f
 5 ...
 6 >>> numbers = 'one', 'two', 'three'
 7 >>> funcs = []
 8 >>> for n in numbers:
 9 ...     funcs.append(wrap(n))
10 ...
11 >>> for f in funcs:
12 ...     f()
13 ...
14 one
15 two
16 three

通常の関数では、関数がリストに追加されると、定義時に9行目で + n +`が評価されます: `+ funcs.append(wrap(n))+

次に、ラムダ関数を使用した同じロジックの実装で、予期しない動作を観察します。

>>>

 1 >>> numbers = 'one', 'two', 'three'
 2 >>> funcs = []
 3 >>> for n in numbers:
 4 ...     funcs.append(lambda: print(n))
 5 ...
 6 >>> for f in funcs:
 7 ...     f()
 8 ...
 9 three
10 three
11 three

実装されているように、ラムダ式の実行時に自由変数 `+ n `がバインドされるため、予期しない結果が発生します。 4行目のPythonラムダ関数は、実行時にバインドされる自由変数である ` n `をキャプチャするクロージャです。 実行時に、7行目で関数「 f 」を呼び出している間、「 n 」の値は「 three +」です。

この問題を克服するために、定義時に次のように自由変数を割り当てることができます。

>>>

 1 >>> numbers = 'one', 'two', 'three'
 2 >>> funcs = []
 3 >>> for n in numbers:
 4 ...     funcs.append(lambda n=n: print(n))
 5 ...
 6 >>> for f in funcs:
 7 ...     f()
 8 ...
 9 one
10 two
11 three

Pythonラムダ関数は、引数に関して通常の関数のように動作します。 したがって、ラムダパラメータはデフォルト値で初期化できます。パラメータ「+ n 」は外側の「 n 」をデフォルト値として使用します。 Pythonラムダ関数は、 ` lambda x = n:print(x)+`と記述でき、同じ結果になります。

Pythonラムダ関数は、7行目で引数なしで呼び出され、定義時に設定されたデフォルト値 `+ n +`を使用します。

ラムダのテスト

Pythonラムダは、通常の関数と同様にテストできます。 「+ unittest 」と「 doctest +」の両方を使用できます。

*`+ unittest +`*

`+ unittest +`モジュールは通常の関数と同様にPythonラムダ関数を処理します:

import unittest

addtwo = lambda x: x + 2

class LambdaTest(unittest.TestCase):
    def test_add_two(self):
        self.assertEqual(addtwo(2), 4)

    def test_add_two_point_two(self):
        self.assertEqual(addtwo(2.2), 4.2)

    def test_add_three(self):
        # Should fail
        self.assertEqual(addtwo(3), 6)

if __name__ == '__main__':
    unittest.main(verbosity=2)

`+ LambdaTest `は、それぞれがラムダ関数として実装された ` addtwo()`のテストシナリオを実行する3つのテストメソッドを持つテストケースを定義します。 ` LambdaTest `を含むPythonファイル ` lambda_unittest.py +`を実行すると、以下が生成されます。

$ python lambda_unittest.py
test_add_three (__main__.LambdaTest) ... FAIL
test_add_two (__main__.LambdaTest) ... ok
test_add_two_point_two (__main__.LambdaTest) ... ok

======================================================================
FAIL: test_add_three (__main__.LambdaTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "lambda_unittest.py", line 18, in test_add_three
    self.assertEqual(addtwo(3), 6)
AssertionError: 5 != 6

----------------------------------------------------------------------
Ran 3 tests in 0.001s

FAILED (failures=1)

予想どおり、2つのテストケースが成功し、 `+ test_add_three `が1つ失敗しました。結果は ` 5 `ですが、予想される結果は ` 6 `でした。 この失敗は、テストケースの意図的な誤りによるものです。 期待される結果を「+6」から「5」に変更すると、「+ LambdaTest +」のすべてのテストが満たされます。

*`+ doctest +`*

`+ doctest `モジュールは ` docstring `からインタラクティブなPythonコードを抽出してテストを実行します。 Pythonラムダ関数の構文は典型的な ` docstring `をサポートしていませんが、名前付きラムダの ` doc +`要素に文字列を割り当てることができます:

addtwo = lambda x: x + 2
addtwo.__doc__ = """Add 2 to a number.
    >>> addtwo(2)
    4
    >>> addtwo(2.2)
    4.2
    >>> addtwo(3) # Should fail
    6
    """

if __name__ == '__main__':
    import doctest
    doctest.testmod(verbose=True)

ラムダ `+ addtwo()`のdocコメントの ` doctest +`は、前のセクションと同じテストケースを説明しています。

`+ doctest.testmod()+`でテストを実行すると、次のものが得られます:

$ python lambda_doctest.py
Trying:
    addtwo(2)
Expecting:
    4
ok
Trying:
    addtwo(2.2)
Expecting:
    4.2
ok
Trying:
    addtwo(3) # Should fail
Expecting:
    6
**********************************************************************
File "lambda_doctest.py", line 16, in __main__.addtwo
Failed example:
    addtwo(3) # Should fail
Expected:
    6
Got:
    5
1 items had no tests:
    __main__
**********************************************************************
1 items had failures:
   1 of   3 in __main__.addtwo
3 tests in 2 items.
2 passed and 1 failed.
***Test Failed*** 1 failures.

失敗したテストの結果は、前のセクションのユニットテストの実行で説明したものと同じ失敗です。

ラムダ関数を文書化するための `+ doc `への割り当てを介して、Pythonラムダに ` docstring `を追加できます。 可能ですが、Pythonの構文は、ラムダ関数よりも通常の関数の ` docstring +`によりよく対応しています。

Pythonでのユニットテストの包括的な概要については、https://realpython.com/python-testing/[Getting Started with Testing in Python]を参照してください。

ラムダ式乱用

この記事のいくつかの例は、プロのPythonコードのコンテキストで記述されている場合、悪用と見なされます。

ラムダ式がサポートしていないものを克服しようとしていることに気付いた場合、これはおそらく通常の関数の方が適していることを示しています。 前のセクションのラムダ式の `+ docstring +`は良い例です。 Pythonラムダ関数がステートメントをサポートしていないという事実を克服しようとすることは、もう1つの危険です。

次のセクションでは、回避すべきラムダの使用例をいくつか示します。 これらの例は、Pythonラムダのコンテキストで、コードが次のパターンを示す状況です。

  • Pythonスタイルガイドに準拠していません(PEP 8)

  • 面倒で読みにくいです。

  • 読みにくいという犠牲を払って不必要に巧妙です。

例外を発生させる

Pythonラムダで例外を発生させようとすると、考え直す必要があります。 そうするためのいくつかの賢い方法がありますが、次のようなものでさえも避けるべきです:

>>>

>>> def throw(ex): raise ex
>>> (lambda: throw(Exception('Something bad happened')))()
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 1, in <lambda>
    File "<stdin>", line 1, in throw
Exception: Something bad happened

Pythonラムダ本体ではステートメントが構文的に正しくないため、上記の例の回避策は、専用関数 `+ throw()+`を使用してステートメント呼び出しを抽象化することです。 このタイプの回避策の使用は避けてください。 このタイプのコードに遭遇した場合、通常の関数を使用するようにコードをリファクタリングすることを検討する必要があります。

不可解なスタイル

すべてのプログラミング言語と同様に、使用されているスタイルのために読みにくいPythonコードがあります。 Lambda関数は簡潔であるため、読みにくいコードの記述に役立ちます。

次のラムダの例には、いくつかの不適切なスタイルの選択肢が含まれています。

>>>

>>> (lambda _: list(map(lambda _: _//2, _)))([1,2,3,4,5,6,7,8,9,10])
[0, 1, 1, 2, 2, 3, 3, 4, 4, 5]

アンダースコア( + _ +)は、明示的に参照する必要のない変数を指します。 しかし、この例では、3つの `+ _ +`が異なる変数を参照しています。 このラムダコードへの最初のアップグレードは、変数に名前を付けることです。

>>>

>>> (lambda some_list: list(map(lambda n: n//2,
                                some_list)))([1,2,3,4,5,6,7,8,9,10])
[0, 1, 1, 2, 2, 3, 3, 4, 4, 5]

確かに、それはまだ読みにくいです。 まだ `+ lambda +`を利用することで、通常の関数はこのコードをより読みやすくするために大いに役立ち、数行と関数呼び出しにロジックを広げます:

>>>

>>> def div_items(some_list):
      div_by_two = lambda n: n//2
      return map(div_by_two, some_list)
>>> list(div_items([1,2,3,4,5,6,7,8,9,10])))
[0, 1, 1, 2, 2, 3, 3, 4, 4, 5]

これはまだ最適ではありませんが、コード、特にPythonラムダ関数をより読みやすくするための可能なパスを示しています。 link:#alternatives-to-lambdas [Lambdasの代替案]では、 `+ map()`と ` lambda +`をリスト内包表記またはジェネレーター式に置き換えることを学びます。 これにより、コードの可読性が大幅に向上します。

Pythonクラス

クラスメソッドをPythonラムダ関数として記述することはできますが、すべきではありません。 次の例は完全に正当なPythonコードですが、 `+ lambda `に依存する型破りなPythonコードを示しています。 たとえば、 ` str `を通常の関数として実装する代わりに、 ` lambda `を使用します。 同様に、 ` brand `と ` year +`はhttps://docs.python.org/3/library/functions.html#property[properties]でもあり、通常の関数やデコレーターではなくラムダ関数で実装されています。

class Car:
    """Car with methods as lambda functions."""
    def __init__(self, brand, year):
        self.brand = brand
        self.year = year

    brand = property(lambda self: getattr(self, '_brand'),
                     lambda self, value: setattr(self, '_brand', value))

    year = property(lambda self: getattr(self, '_year'),
                    lambda self, value: setattr(self, '_year', value))

    __str__ = lambda self: f'{self.brand} {self.year}'  # 1: error E731

    honk = lambda self: print('Honk!')     # 2: error E731

スタイルガイドの適用ツールであるhttp://flake8.pycqa.org/[+ flake8 +]のようなツールを実行すると、 `+ str `および ` honk +`に対して次のエラーが表示されます。

E731 do not assign a lambda expression, use a def

`+ flake8 `はプロパティでのPythonラムダ関数の使用に関する問題を指摘していませんが、 ` '_ brand' +`や `などの複数の文字列を使用しているため、読みにくくエラーが発生しやすくなっています。 + '_ year' + `。

`+ str +`の適切な実装は次のようになります:

def __str__(self):
    return f'{self.brand} {self.year}'

`+ brand +`は次のように記述されます。

@property
def brand(self):
    return self._brand

@brand.setter
def brand(self, value):
    self._brand = value

一般的なルールとして、Pythonで記述されたコードのコンテキストでは、ラムダ式よりも通常の関数を優先します。 それにもかかわらず、次のセクションで見るように、ラムダ構文の恩恵を受ける場合があります。

ラムダ式の適切な使用

Pythonのラムダは論争の対象になる傾向があります。 Pythonのラムダに対するいくつかの引数は次のとおりです。

  • 読みやすさの問題

  • 機能的な考え方の賦課

  • `+ lambda +`キーワードを使用した重い構文

Pythonでのこの機能の単なる存在を疑問視する激しい議論にもかかわらず、ラムダ関数には、Python言語および開発者に価値を提供するプロパティがあります。

次の例は、ラムダ関数の使用が適切であるだけでなく、Pythonコードで推奨されるシナリオを示しています。

古典的な機能構築物

Lambda関数は、組み込み関数https://docs.python.org/3/library/functions.html#map [+ map()+]およびhttps://docs.python.org/で定期的に使用されます3/library/functions.html#filter [+ filter()+]、およびhttps://docs.python.org/3/library/functools.html?highlight=reduce#functools.reduce[+モジュールhttps://docs.python.org/3/library/functools.html [+ functools `]で公開されているfunctools.reduce() `]。 次の3つの例は、ラムダ式をコンパニオンとして使用してこれらの関数を使用するそれぞれの例です。

>>>

>>> list(map(lambda x: x.upper(), ['cat', 'dog', 'cow']))
['CAT', 'DOG', 'COW']
>>> list(filter(lambda x: 'o' in x, ['cat', 'dog', 'cow']))
['dog', 'cow']
>>> from functools import reduce
>>> reduce(lambda acc, x: f'{acc} | {x}', ['cat', 'dog', 'cow'])
'cat | dog | cow'

より関連性の高いデータがありますが、上記の例に似たコードを読む必要があります。 そのため、これらの構成要素を認識することが重要です。 それにもかかわらず、これらの構成には、よりPythonicと見なされる同等の代替があります。 link:#alternatives-to-lambdas [Alternatives to Lambdas]では、高階関数とそれに付随するラムダを他のより慣用的な形式に変換する方法を学びます。

主な機能

Pythonのキー関数は、名前付き引数としてパラメーター `+ key `をとる高階関数です。 ` key `は、 ` lambda +`になり得る関数を受け取ります。 この関数は、キー関数自体によって駆動されるアルゴリズムに直接影響します。 主な機能は次のとおりです。

  • * + sort()+:*リストメソッド

  • * + sorted()++ min()++ max()+:*組み込み関数

  • *ヒープキューアルゴリズムモジュール + heapq +`内の `+ nlargest()+`および `+ nsmallest()+: *

文字列として表されるIDのリストをソートしたいと想像してください。 各IDは、文字列「+ id 」と数字のhttps://realpython.com/python-string-split-concatenate-join/[concatenation]です。 組み込み関数 ` sorted()+`を使用してこのリストを並べ替えると、デフォルトでは、リスト内の要素が文字列であるため、辞書式順序が使用されます。

ソートの実行に影響を与えるために、IDに関連付けられた番号をソートで使用するように、ラムダを名前付き引数 `+ key +`に割り当てることができます。

>>>

>>> ids = ['id1', 'id2', 'id30', 'id3', 'id22', 'id100']
>>> print(sorted(ids)) # Lexicographic sort
['id1', 'id2', 'id30', 'id3', 'id22', 'id100']
>>> sorted_ids = sorted(ids, key=lambda x: int(x[2:])) # Integer sort
>>> print(sorted_ids)
['id1', 'id2', 'id3', 'id22', 'id30', 'id100']

UIフレームワーク

Tkinter、https://wxpython.org/[wxPython]、またはhttps://ironpython.net/を使用した.NET Windows FormsなどのUIフレームワーク[IronPython]は、ラムダ関数を利用して、UIイベントに応じてアクションをマッピングします。

以下の単純なTkinterプログラムは、_Reverse_ボタンのコマンドに割り当てられた `+ lambda +`の使用方法を示しています。

import tkinter as tk
import sys

window = tk.Tk()
window.grid_columnconfigure(0, weight=1)
window.title("Lambda")
window.geometry("300x100")
label = tk.Label(window, text="Lambda Calculus")
label.grid(column=0, row=0)
button = tk.Button(
    window,
    text="Reverse",
    command=lambda: label.configure(text=label.cget("text")[::-1]),
)
button.grid(column=0, row=1)
window.mainloop()

ボタン_Reverse_をクリックすると、ラムダ関数をトリガーするイベントが発生し、ラベルが_Lambda Calculus_から_suluclaC adbmaL_* に変更されます。

NETプラットフォーム上のwxPythonとIronPythonは、イベントを処理するための同様のアプローチを共有しています。 `+ lambda `は発生イベントを処理する1つの方法ですが、同じ目的で関数を使用することもできます。 必要なコードの量が非常に少ないときに、 ` lambda +`を使用することは、自己完結型で冗長性が低くなります。

wxPythonを調べるには、https://realpython.com/python-gui-with-wxpython/[wxPythonを使用してPython GUIアプリケーションを構築する方法]を確認してください。

Pythonインタプリタ

インタラクティブインタープリターでPythonコードを使用している場合、Pythonラムダ関数は多くの場合祝福です。 簡単なワンライナー関数を簡単に作成して、インタープリターの外では日の目を見ることのないコードの一部を調べることができます。 インタプリタで記述されたラムダは、迅速な発見のために、使用後に捨てることができるスクラップペーパーのようなものです。

+ timeit +

Pythonインタープリターでの実験と同じ精神で、モジュール `+ timeit `は小さなコードフラグメントの時間を計る関数を提供します。 特に ` timeit.timeit()+`は、文字列でPythonコードを渡して直接呼び出すことができます。 例を示しましょう。

>>>

>>> from timeit import timeit
>>> timeit("factorial(999)", "from math import factorial", number=10)
0.0013087529951008037

ステートメントが文字列として渡されるとき、 `+ timeit()`は完全なコンテキストを必要とします。 上記の例では、これは、タイミングをとるメイン関数に必要な環境を設定する2番目の引数によって提供されます。 そうしないと、 ` NameError +`例外が発生します。

別のアプローチは、 `+ lambda +`を使用することです:

>>>

>>> from math import factorial
>>> timeit(lambda: factorial(999), number=10)
0.0012704220062005334

このソリューションは、より簡潔で読みやすく、インタープリターにすばやく入力できます。 `+ lambda `バージョンでは実行時間がわずかに短くなりましたが、関数を再度実行すると ` string `バージョンではわずかな利点があります。 「 setup +」の実行時間は全体の実行時間から除外されており、結果に影響はありません。

モンキーパッチング

テストでは、特定のソフトウェアの通常の実行中に対応する結果が異なるか、完全にランダムであることが予想される場合でも、繰り返し可能な結果に依存することが必要になる場合があります。

実行時にランダムな値を処理する関数をテストするとします。 ただし、テストの実行中は、予測可能な値に対して繰り返し可能な方法でアサートする必要があります。 次の例は、 `+ lambda +`関数を使用して、モンキーパッチがどのように役立つかを示しています。

from contextlib import contextmanager
import secrets

def gen_token():
    """Generate a random token."""
    return f'TOKEN_{secrets.token_hex(8)}'

@contextmanager
def mock_token():
    """Context manager to monkey patch the secrets.token_hex
    function during testing.
    """
    default_token_hex = secrets.token_hex
    secrets.token_hex = lambda _: 'feedfacecafebeef'
    yield
    secrets.token_hex = default_token_hex

def test_gen_key():
    """Test the random token."""
    with mock_token():
        assert gen_token() == f"TOKEN_{'feedfacecafebeef'}"

test_gen_key()

コンテキストマネージャは、標準ライブラリ(この例では、https://docs.python.org/3/library/secrets.html#module-secrets [+ secrets +])から関数にパッチを適用する操作を隔離するのに役立ちます。 `+ secrets.token_hex()+`に割り当てられたラムダ関数は、静的な値を返すことでデフォルトの動作を置き換えます。

これにより、 `+ token_hex()`に依存する関数を予測可能な方法でテストできます。 コンテキストマネージャーを終了する前に、 ` token_hex()`のデフォルトの動作に依存する可能性のあるテストの他の領域に影響する予期しない副作用を排除するために、 ` token_hex()+`のデフォルトの動作が再確立されます。

`+ unittest `や ` pytest +`のような単体テストフレームワークは、この概念をより高度なレベルに引き上げます。

まだ `+ lambda `関数を使用している ` pytest +`では、同じ例がよりエレガントで簡潔になります:

import secrets

def gen_token():
    return f'TOKEN_{secrets.token_hex(8)}'

def test_gen_key(monkeypatch):
    monkeypatch.setattr('secrets.token_hex', lambda _: 'feedfacecafebeef')
    assert gen_token() == f"TOKEN_{'feedfacecafebeef'}"

https://docs.pytest.org/en/latest/monkeypatch.html[pytest `+ monkeypatch `フィクスチャ]を使用すると、決定的な値を返すラムダで ` secrets.token_hex()`が上書きされます。 + feedfacecafebeef + `。テストを検証できます。 pytestの ` monkeypatch `フィクスチャを使用すると、オーバーライドのスコープを制御できます。 上記の例では、モンキーパッチを使用せずに後続のテストで ` secrets.token_hex()+`を呼び出すと、この関数の通常の実装が実行されます。

`+ pytest +`テストを実行すると、次の結果が得られます。

$ pytest test_token.py -v
============================= test session starts ==============================
platform linux -- Python 3.7.2, pytest-4.3.0, py-1.8.0, pluggy-0.9.0
cachedir: .pytest_cache
rootdir:/home/andre/AB/tools/bpython, inifile:
collected 1 item

test_token.py::test_gen_key PASSED                                       [100%]

=========================== 1 passed in 0.01 seconds ===========================

`+ gen_token()+`が実行されたことを検証したため、テストに合格し、テストのコンテキストで期待される結果が得られました。

ラムダの代替品

`+ lambda +`を使用する大きな理由がありますが、その使用が嫌われる場合があります。 それでは、代替手段は何ですか?

+ map()++ filter()+、および `+ functools.reduce()+`のような高階関数は、特にリストの理解や、ジェネレータ式。

リスト内包表記の詳細については、https://realpython.com/courses/using-list-comprehensions-effectively/[リスト内包表記の効果的な使用]をご覧ください。

Map

組み込み関数 `+ map()+`は、関数を最初の引数として受け取り、その関数を2番目の引数 iterable の各要素に適用します。 イテラブルの例は、文字列、リスト、およびタプルです。 イテラブルとイテレータの詳細については、https://realpython.com/lessons/looping-over-iterables/[Iterables and Iterators]をご覧ください。

`+ map()`は、変換されたコレクションに対応する反復子を返します。 例として、文字列のリストを各文字列を大文字にして新しいリストに変換する場合、次のように ` map()+`を使用できます。

>>>

>>> list(map(lambda x: x.capitalize(), ['cat', 'dog', 'cow']))
['Cat', 'Dog', 'Cow']

`+ map()`によって返されたイテレータを、Pythonシェルインタープリターで表示できる拡張リストに変換するには、 ` list()+`を呼び出す必要があります。

リスト内包表記を使用すると、ラムダ関数を定義して呼び出す必要がなくなります。

>>>

>>> [x.capitalize() for x in ['cat', 'dog', 'cow']]
['Cat', 'Dog', 'Cow']

フィルタ

別の古典的な機能構成である組み込み関数 `+ filter()+`は、リスト内包表記に変換できます。 最初の引数としてhttps://en.wikipedia.org/wiki/Predicate_(mathematical_logic)[predicate]を取り、2番目の引数としてiterableを取ります。 述語関数を満たす初期コレクションのすべての要素を含む反復子を作成します。 整数のリスト内のすべての偶数をフィルタリングする例を次に示します。

>>>

>>> even = lambda x: x%2 == 0
>>> list(filter(even, range(11)))
[0, 2, 4, 6, 8, 10]

`+ filter()`はイテレータを返すため、イテレータを指定してリストを作成する組み込み型 ` list +`を呼び出す必要があることに注意してください。

リスト内包構造を活用する実装は、以下を提供します:

>>>

>>> [x for x in range(11) if x%2 == 0]
[0, 2, 4, 6, 8, 10]

減らす

Python 3以降、 `+ reduce()`は組み込み関数から ` functools `モジュール関数に移行しました。 ` map()`と ` filter()`のように、最初の2つの引数はそれぞれ関数と反復可能です。 また、結果のアキュムレータの初期値として使用される3番目の引数として初期化子を取る場合があります。 イテラブルの各要素に対して、 ` reduce()+`は関数を適用し、イテラブルが使い果たされたときに返される結果を蓄積します。

ペアのリストに「+ reduce()+」を適用し、各ペアの最初のアイテムの合計を計算するには、次のように記述できます。

>>>

>>> import functools
>>> pairs = [(1, 'a'), (2, 'b'), (3, 'c')]
>>> functools.reduce(lambda acc, pair: acc + pair[0], pairs, 0)
6

generator expressionを例の `+ sum()+`の引数として使用する、より慣用的なアプローチは次のとおりです。

>>>

>>> pairs = [(1, 'a'), (2, 'b'), (3, 'c')]
>>> sum(x[0] for x in pairs)
6

わずかに異なる、おそらくよりクリーンなソリューションにより、ペアの最初の要素に明示的にアクセスし、代わりにアンパックを使用する必要がなくなります。

>>>

>>> pairs = [(1, 'a'), (2, 'b'), (3, 'c')]
>>> sum(x for x, _ in pairs)
6

アンダースコア( + _ +)の使用は、ペアの2番目の値を無視できることを示すPythonの規則です。

`+ sum()+`は一意の引数を取るため、ジェネレータ式を括弧で囲む必要はありません。

LambdasはPythonicですか?

PEP 8(Pythonコードのスタイルガイド)には次のように書かれています。

_ ラムダ式を直接識別子にバインドする割り当てステートメントの代わりに、常にdefステートメントを使用します。 (https://www.python.org/dev/peps/pep-0008/#programming-recommendations [ソース]) _

これは、主に関数を使用する必要があり、より多くの利点がある場合、識別子にバインドされたラムダを使用することを強く推奨します。 PEP 8では、 `+ lambda +`の他の使用法については言及していません。 前のセクションで見たように、ラムダ関数には制限がありますが、確かに良い使用法があります。

質問に答える可能な方法は、利用可能なPythonicが他にない場合、ラムダ関数は完全にPythonicであるということです。 「Pythonic」の意味を定義せずに、自分の考え方に最適な定義と、個人またはチームのコーディングスタイルを残します。

Python `+ lambda +`の狭い範囲を超えて、https://realpython.com/python-pep8/[PEP 8で美しいPythonコードを書く方法]は、Pythonのコードスタイルに関してチェックアウトしたい素晴らしいリソースです。 。

結論

Pythonの `+ lambda +`関数の使用方法がわかったので、次のことができます。

  • Pythonラムダを作成し、匿名関数を使用する

  • ラムダまたは通常のPython関数の間で賢明に選択する

  • ラムダの過度の使用を避ける

  • 高次関数またはPythonキー関数でラムダを使用する

数学に興味があるなら、https://en.wikipedia.org/wiki/Lambda_calculus [lambda calculus]の魅力的な世界を探検する楽しみがあります。

Pythonラムダは塩のようなものです。 スパム、ハム、卵にピンチすると風味が向上しますが、多すぎると料理が損なわれます。

  • __クイズに挑戦:*インタラクティブな「Python Lambda関数」クイズで知識をテストします。 完了すると、学習の進捗状況を経時的に追跡できるようにスコアを受け取ります。

link:/quizzes/python-lambda/[クイズに挑戦»]

注: Monty Pythonにちなんで命名されたPythonプログラミング言語は、https://en.wikipedia.org/wiki/Spam_%28Monty_Python%29 [+ spam +]、 + ham +、および + eggs +の使用を好みます。 `従来の + foo + + bar + 、および + baz + `の代わりに、メタ構文変数として。