読者です 読者をやめる 読者になる 読者になる

元理系院生の新入社員がPythonとJavaで色々頑張るブログ

プログラミングや機械学習について調べた事を書いていきます

lambda式はすごく面白い

最近lambda式にハマってしまい何でもかんでもlambda式で書こうとしています。

「なんでもかんでもlambda式で書いてやるぜ!」というのはちょっとアレですが、lambda式は使ってみると割と便利なので、lambda式のちょっとしたメリットについて少し取り上げてみます。


そもそもlambdaとはなんぞや。

lambdaとは無名関数を表現する記法の一つです。

無名関数とは名前の通り、名前の付いて無い関数のことです。


pythonだったらa,bを引数として受け取り、その和を返す関数を

def func(a, b):
    return a+b

・・・と、funcと名前を付けて記述しますね。

これに対し、lmabda式を使って、引数a,bを受け取りその和を返す関数を記述すると

lambda a, b : a + b

となります。

lambda式を知らないと「なんじゃこりゃ?」となるので(ぼくがなった)、かるーく説明します。

lambda a, b : a + b

の最初のlambdaは予約語で「これからlambda式書きますよ~」と処理系に教えて上げるキーワードです。defと同じ意味で、defが「これから名前付きの関数を定義するよ~」と教えるのに対し、lambdaは「これから名前無い(無名)関数を定義するよ~」とアッピルしています。

lambdaの隣にあるa, bは引数を表し、

def func(a, b):

のカッコの中と同じ意味を持っています。

次に「:」(コロン)を挟んで右側が、返り値を表しています。

普通の関数における

return a + b

と同じ意味です。

コロンを挟んで左側が引数のエリア、右側が返り値のエリアとおぼえておけば問題無いと思います。

ちなみに引数は「,」(カンマ)で区切ればいくつでも使えますし、なくても構いません。

しかし、戻り値は返さないとダメみたいです。この辺りは計算理論の小難しい話になりますが、使う上ではあまり考えなくて良いと思います。

さっきのラムダ関数を実際に使ってみると以下のようになります。

(lambda a, b : a + b)(1, 2)

こうすると、この式は1+2すなわち3を返してくれる。

また、

i = (lambda a, b: a + b)(1, 2)

の様に記述すればiに3が代入される感じ。

で?結局lambda使うと何が嬉しいの?

端的に言うと関数を式として扱うことが出来るのが嬉しいです。

式として扱うことが出来ると、pythonだと変数に格納することが出来ます。

例えば

f = lambda a, b: a + b

なーんて記述すると、次からは

f(1, 2)

とか

f(3, 5)

って関数を使うことが出来ちゃいます。

「おおい!それって無名関数じゃないじゃん?と言うか普通にdef func(a, b)~って定義するのと何が違うんだよ!」って思うと思います。(思いますよね?)

実は、名前をつけた無名関数ではなくて、無名関数に名前をつけてあげる事にメリットがあるのです。

さっきの

f = lambda a, b : a + b

という代入式によって、無名関数は見事に名前を持つ事が出来ました。

この名前を持った関数fは変数として扱うことが出来るので、

他の関数の引数に渡し、他の関数でさっき名前を付けた無名関数を使うことが出来るのです!

パッと言われ「へぇ~~~!!!そうそう、超スゴイじゃん!」とはなかなかならないと思うので、凄さを一発で表現する華麗なコードをババっと載せたい所ですが、今回はやめておきます。(お察しください)

関数に無名関数を渡す喜びの一例
「関数に無名関数を渡し、そこで使ってもらう」という利用方法が取られているコードとして、pythonの標準関数のmap関数があります。

map関数は引数としてlambda式とイテレータを受け取り、イテレータの全ての要素に対し、lambda式を適用し結果を返してくれます。

例えば、

lambda式として引数を1つ受け取り、2倍にして返す無名関数

f = lambda x: 2*x

イテレータとして、長さ適当の整数が格納されたlist

itr = [1, 5, 2, 3,20, 2]

をmap関数に渡してみます。

map(f, itr)

するとmap型はitrの各要素に順番にアクセスしていき、fを適用していきます。

全ての要素に対し処理を行ったら、map関数はイテレータを返します。

この時帰ってくるイテレータはitrの各要素が2倍になった値です。

[2, 10, 4, 6, 40, 4]

こ~んな感じに、map関数に対し、自分で定義したlambda式を渡し、map関数の中でlambda式を使ってもらう~という事が出来るのがlambda式の特徴でありメリットです!

他にもイテレータの内包表記で使ったりワンライナーで黒魔術的なコードを書いたり等々の様々な使い方があるので、活用していきたいですね。