4.7. lambda 関数を使う

Python はその場で 1 行のミニ関数を定義できる構文をサポートしています. その Lisp から拝借した所謂 lambda 関数は, 関数が書けるところならどこでも使えます.

Example 4.20. lambda 関数の紹介

>>> def f(x):
...     return x*2
...     
>>> f(3)
6
>>> g = lambda x: x*2  1
>>> g(3)
6
>>> (lambda x: x*2)(3) 2
6
1 これは 1 つ上の通常の関数と同じことをする lambda 関数です. 簡潔な構文に注意してください. 引数のリストに丸括弧は付いていませんし, return キーワードもありません (関数部分は 1 つの式でしか有り得ないので, 暗黙のうちに存在しています). また, 関数には名前がありませんが, 割り当てられた変数を通して呼び出すことができます.
2 lambda 関数を変数に割り当てることをせず使うこともできます. これはそんなに知られていないことかもしれませんが, ラムダは単なるインライン関数だということを示しているだけです.

一般的な話をすると, lambda 関数は (オプションの引数も含め) 任意の数の引数を取り, 1 つの式の返り値を返す関数です. lambda 関数はコマンドを含むことはできず, 1 つより多く式を含むこともできません. lambda 関数には過剰にものを詰め込もうとしないでください. もっと複雑なものが必要な場合は, 代わりに通常の関数を定義して, あなたが望むものを作ってください.

Note
lambda 関数はスタイルに関わる問題です. それは絶対使わなければいけないものではありません. それが使える場所では, 代わりに通常の関数を別に定義して使うこともできます. 私は, ある固有の再利用できないコードをカプセル化し, たくさんの小さな 1 行関数を撒き散らさないようにするために, lambda 関数を使います.

4.7.1. 現実の世界の lambda 関数

以下は apihelper.py にある lambda 関数です.

    processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)

簡単な形の and-or トリックを使っていることと, lambda 関数は論理値として常に真なのでこの形で問題無いことに注意してください. (これは lambda 関数が偽の値を返せないということではありません. 関数は常に真であり, どんな値でも返せます.)

また split を引数無しで使っていることに注意してください. あなたは 1 つまたは 2 つの引数で関数を使うのは既に見たと思いますが, 引数無しで使うとホワイトスペースで分割します.

Example 4.21. 引数無しの split

>>> s = "this   is\na\ttest"  1
>>> print s
this   is
a	test
>>> print s.split()           2
['this', 'is', 'a', 'test']
>>> print " ".join(s.split()) 3
'this is a test'
1 ここでは 3 連引用符の代わりにエスケープ文字を使って, 複数行文字列を定義しています. \n はキャリッジ・リターン (CR) で, \t はタブ文字です.
2 引数無しの split はホワイトスペースで分割を行います. なので, 3 つのスペース, キャリッジ・リターン, タブ文字の扱いに違いはありません.
3 文字列を split で分割し, 1 つのスペースを区切り文字として join で再結合することで, ホワイトスペースを正規化することができます. これは info 関数が複数行の doc string を 1 行にまとめるために行っていることです.

では実際に info 関数は lambda 関数と splitand-or トリックを使って何をしているのでしょうか?

    processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)

processFunc は関数ですが, どちらの関数になるかは collapse 変数の値に依存します. collapse が真だった場合, processFunc(string) はホワイトスペースを折り畳みます. そうでなければ, processFunc(string) は引数に変更を加えないまま返します.

これを Visual Basic のようなより堅牢性の低い言語でやるには, 文字列と collapse 引数を取り, if 文を使ってホワイトスペースを折り畳むかどうか判断し, 適切な値を返す関数を作るのでしょう. 関数は有り得る全てのケースを扱う必要があるので, おそらくこれでは十分ではありません. それを呼び出すたびに, ホワイトスペースを折り畳むかどうかを, あなたが何をしたいかを考える前に判断する必要があります. Python では, その判断するロジックを関数から取り出し, 厳密にあなたのしたいことを (そしてそれだけを) する特注品の lambda 関数を定義することができます. この方が効率的で, エレガントで, 「しまった, 引数の順序を逆だと思ってた」という種類のひどいエラーをしにくくなります.

lambda 関数についてさらに知るには