Pythonのlambda(ラムダ)式の使い方
lambda式というのは、関数を簡易的に定義する方法。
Pythonでは、defで関数の定義ができますが、引数xに対して、返り値x*2を返す関数を使いたい場合にlambda式を使います。いちいちdefで関数定義するのは冗長な感じ…もっと簡易的に使いたいな!ってときに手抜きするためのもの。
例えばこんな感じ。
#!/usr/bin/python3 # xの値を2倍して表示 x=2 x=x*2 print( "x=",x ) # yの値を、引数を2倍する関数に渡して表示 y=2 myfunc=lambda a:a*2 print ( "y=",myfunc(y) )
myfunc=…の行で、ワンラインで簡易的な関数定義ができるイメージですね。
実行結果はこう。
x= 4 y= 4
んー、でもこれって、なんの役に立つの?
実は関数を指定するmap関数などで、便利さを実感できます。
Pythonでmapとlambdaを組み合わせて、複数要素を同時加工
map関数は、イテラブルオブジェクトに対して各要素に同時に値の加工を適用できる関数。
イテラブルオブジェクトというのは、listとかタプルのような要素を順番に取り出せるデータのこと。
実際に、mapとlambdaを組み合わせたサンプルコードはこちら。
#!/usr/bin/python3 import math # list型のmylistを定義 mylist=[1,2,3,4,5,6] # mylist を表示 print( "mylist=",mylist ) # map関数で各要素の平方根を求める mylist_sqrt=map( math.sqrt,mylist ) print( "mylistの平方根=",list(mylist_sqrt) ) # map+lambdaで、各要素に1を足して2で割った値を求める mylist_2=map( lambda x:(x+1)/2,mylist ) print( "mylistの各要素に1足して2で割る=",list(mylist_2) )
mapは、各要素にforループも使わずに同時多発的に加工できる強力な関数。ここにlambdaを組み込むことで、自由度が広がるというわけですね。もちろん、defで定義した関数も指定できますが、単純な関数なら、1行で記述したほうが、処理の流れも追いやすいというわけ。
実行するとこうなります。
$ ./map.py mylist= [1, 2, 3, 4, 5, 6] mylistの平方根= [1.0, 1.4142135623730951, 1.7320508075688772, 2.0, 2.23606797749979, 2.449489742783178] mylistの各要素に1足して2で割る= [1.0, 1.5, 2.0, 2.5, 3.0, 3.5]
map関数の返り値は、mapオブジェクトなので表示させるためにlistでキャストしています。
そのままprintしようとすると、オブジェクトのアドレスが表示されてしまい、中身の表示ができません。
以下は、「print(myfunc_2)」を実行したときの例です。
map関数の返り値を直接printするとこうなる= <map object at 0xb77e0c6c>
Pythonでsortedにlambdaを組み合わせて、辞書型のソートをおこなう
lambdaがよく使われるケースの一つが、辞書型をソートするsorted関数との組み合わせです。sortedは辞書型やタプルなどの更新不可(イミュータブル)なオブジェクトに対して使われるソート関数。
sortedは、元のオブジェクトを更新せず、ソート済みの新しいオブジェクトを生成します。
以下は、sortedとlambdaを組み合わせて、
cat sorted.py #!/usr/bin/python3 # 辞書型を定義 mydic={'dog':'いぬ','rabbit':'うさぎ','cat':'ねこ'} # 辞書の値(Value)を使ってソート value=sorted( mydic.items(), key=lambda x:x[1] ) print( "元のオブジェクト:", mydic ) print( "値でソート:", value )
実行するとこうなります。
$ ./sorted.py 元のオブジェクト: {'cat': 'ねこ', 'dog': 'いぬ', 'rabbit': 'うさぎ'} 値でソート: [('dog', 'いぬ'), ('rabbit', 'うさぎ'), ('cat', 'ねこ')]
mydic.items()という指定は、辞書のキーと値のセットを指します。
日本語の場合、辞書型の値「いぬ」や「うさぎ」をあいうえお順にソートするので、いぬ、うさぎ、ねこの順に並び替えられます。
Pythonのlambdaでif分岐を使いたい場合
lambda式内で、直接if文を使うことはできません。
しかし、三項演算子を使って、条件分岐を記述することが可能です。
関連 Pythonのif文
以下は、リストの要素に対して、2で割り切れたら0を、割り切れなければ1を新しいリストにセットするというサンプルコードです。
$ cat sankousshiki.py #!/usr/bin/python3 # リストを定義 mylist=[1,2,3,4,5,6] # リストの要素に対して、2で割り切れたら0、割り切れないなら1をセット x=map( lambda x:0 if x % 2 else 1, mylist ) # 生成したリストを表示 print( "元のリスト:", mylist ) print( "2で割り切れるリスト:", list( x ) )
実行するとこうなります。
$ ./sankousshiki.py 元のリスト: [1, 2, 3, 4, 5, 6] 2で割り切れるリスト: [0, 1, 0, 1, 0, 1]
三項演算子はネストできるので、さらに複雑な条件分岐も記述可能。しかし、パッと見て、なんの処理をしているのかわかりにくくなるため、開発プロジェクトなど、多人数でソースコードを編集・修正するような場では、多用は避けたほうが良いかもしれません。
Pythonのlambdaまとめ
- lambdaは無名関数。defを使わずに簡易的に関数定義が可能。
- mapとlambdaを組み合わせると、イテラブルオブジェクトの要素全体に関数を適用できる
- lambda式では、三項演算子でif分岐が可能。ネストもできる。