調べ物した結果

現役SEが仕事と直接関係ないことを調べた結果とか感想とか

pythonのlambda式のちょっとしたサンプル

概要


個人的に、pythonのlambda式がとっつきにくいなぁと感じたから、写経も兼ねて。
確認環境はwindows10+python3.6です。

基本形

val = (lambda price,tax:(price * (1 + tax)))(100, 0.08)
print(val)

消費税の計算。 printの結果は「108」
ざっと書いたけどすでに分かりにくい気がしてる。

lambda

でこれからlambda式が開始されることを宣言している。
次の

price, tax

はそれぞれ引数。price,taxという引数を持つということを宣言している。
:をはさんで

( price * (1 + tax))

が実装部分。ここはロジックになる。

def unknown(price, tax):
  return price * ( 1 + tax)

と同等。

(lambda ~)

でかっこでくくってるのは、そこまでの境界。続く(100, 0.08)でようやく作ったlambda式が呼ばれてる形と解釈している。
いやーわかりにくいっす。
val = 100 * (1 + 0.0.8)。でよくない?たぶんこの場合はそれでもいいと思う。
けど、式にすることで明示的に意味のある塊になるのでどうだろうか。個人的にはそれならメソッドに切ればいいじゃないか。と思う。
じゃーいつ使うのよ。

minなる関数


minという最小値を取得する関数がある。ただの配列ならいいけど、特定の規則に従ってソートした結果の最小値が欲しい。
という時もあるだろう。(c#だとCompareつくったりするよね。そーゆーことだと思っている。)
たとえば

sample = {("male",150):1,("female",160):2, ("male",170):3, ("female",180):4}
print(sample)

こんな感じ。男女混じって現状身長順に並べているが、例えば女性の中で
一番身長が低い。を取るにはどうするか。という時。とりあえずそのまま使ってみる。

sample = {("male",150):1,("female",160):2, ("male",170):3, ("female",180):4}

print(min(sample))

結果は

('female', 160)

偶然にも答えはあってるんじゃが・・・何をもってこれが抽出されているのかわからないので違うったら違うよね。
ややこしいから男性の最小身長を出すことにしよう

sample = {("male",150):1,("female",160):2, ("male",170):3, ("female",180):4}

print(min(sample, key= lambda x: x[1] if x[0] == "male" else 999))

こうなる。
使い方があっているのか怪しいが。 maleの条件合致しているときはそのままtupleの値を使う。
とっつきにくいところは変数「x」か。minのlambda式で使う場合、xにはsampleの子要素が順番に渡される形になる。
つまり
x= sample[0]
x= sample[1]・・・
のように。順次渡されるイメージで問題ないとおもう。
後は合致していないときは「999(int.maxValueとかないかな)」を渡して順序の対象外にする。そんな感じ。
個人的にはフィルタをかけたいのだけれど(C#Linqのように)

で、各組合せをだすとしたのようになる。

sample = {("male",150):1,("female",160):2, ("male",170):3, ("female",180):4}

intmax = 999
intmin = -999

# 男性最小
print(min(sample, key= lambda x: x[1] if x[0] == "male" else intmax))
# 男性最大
print(max(sample, key= lambda y: y[1] if y[0] == "male" else intmin))
# 女性最小
print(min(sample, key= lambda z: z[1] if z[0] == "female" else intmax))
# 女性最大
print(max(sample, key= lambda x: x[1] if x[0] == "female" else intmin))

それぞれ結果も
('male', 150)
('male', 170)
('female', 160)
('female', 180)
で大満足。これでlambdaも怖くないね。