Python の lambda式

まとめながら理解してみた。

Q. lambda 関数とdef ステートメントの関係は? 両者を比較してください。

lambda と def は、どちらも関数オブジェクトを作ることができる、という点では共通しています。ただし、lambda は式なので、def ステートメントとは違い、文法的にdefステートメントが使用できない箇所でも使えます。たとえば、リストのリテラル、関数の呼び出しコードなどの中でも使えるのです。lambda は必ず使わなくてはならない、というものではありません。lambda と同等のコードは、必ずdef を使って書くことができるからです。ただ、def を使った場合、関数には最初からすべて名前がある、ということになります。lambda は、特定の場所だけで使われ、他に応用される可能性の低い、簡単な関数を作る場合に便利です。lambda で得られる戻り値は1つに限定されています。ステートメントのブロックには対応できないので、大規模な関数の作成には向きません。

by はじめてのPython 第3版 pp.405

で、結局使いどころはどこなの?という疑問。
具体的にいくつか試してみた。

、、、が、たぶん例が良くない。

せっかくの無名関数なのに、、、

>>> func = lambda a,b,c:a+b+c
>>> func(2,3,4)
9
>>> def func(a,b,c):return a+b+c
...
>>> func(2,3,4)
9

なんか呼び出し方が複雑になってね?

>>> def knights():
...     title = 'Sir'
...     return (lambda x: title + ' ' + x)
...
>>> knights()('hoge')
'Sir hoge'
>>> def knights_def(x):
...     title = 'Sir'
...     return title + ' ' + x
...
>>> knights_def('hoge')
'Sir hoge'

lambda 式の解説が、上記あたりから始まるから、わけわからなくなるんだと思った。やっぱり lambda 式を使わないとメンドクサイよね?と思うような例をバシッと最初に示して欲しいものだ。

ちょっと使いどころがわかった例

>>> L=[(lambda x:x**2),(lambda x:x**3), (lambda x:x**4)]
>>> for f in L:
...     print f(2)
...
4
8
16
>>> print L[0](3)
9
>>> print L[1](3)
27
>>> print L[2](3)
81

この辺でようやく勘所が、ディクショナリとかmap関数で使うといいよ!ってのも納得できる。

ディクショナリで使った例

>>> lambda_switch={'sum':(lambda a,b:a+b), 'diff':(lambda a,b:a-b)}
>>> lambda_switch['sum'](2,3)
5
>>> lambda_switch['diff'](2,3)
-1

上記のように、swith/case文のような多分岐をディクショナリを使うには重宝しそう。

map関数で使った例

>>> nums=[1,1,2,3,5,8,13]
>>> def sq(x):
...     return x**2
...
>>> map(sq, nums)
[1, 1, 4, 9, 25, 64, 169]
>>> nums=[1,1,2,3,5,8,13]
>>> map((lambda x:x**2), nums)
[1, 1, 4, 9, 25, 64, 169]

いちいち関数をdefする必要がない。
引数が複数ある場合は、↓みたいな感じ。

>>> nums=[1,1,2,3,5,8,13]
>>> nums2=[0,1,1,2,3,5,8]
>>> map((lambda x,y:x-y), nums, nums2)
[1, 0, 1, 1, 2, 3, 5]

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*


次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <img localsrc="" alt="">