にほんごのれんしゅう

日本語として伝えるための訓練を兼ねたテクログ

pythonにおいて如何にLAMBDAが重要か

モチベーション

勉強会の資料作成用にメモをとっていた. 読み物して耐えられるレベルにないが,何を思考し,何を重要視していたのかを 忘却しないで次の私自身の成長の機会につなげるための資料とする

pythonにおいて如何にLAMBDAが重要か

パイソンの書きやすさは常に安定的なわかりやすさといのは嘘カモ

FizzBuzzを例にとってみてみましょう

多くの人が見ているのはこのようなものなのだろうか

for i in range(1, 100):
  if i % 3 == 0:
    print 'Fizz',
  if i % 5 == 0:
    print 'Buzz',
  if i % 3 != 0 and i % 5 != 0:   
    print i,
  print 
 python2.7

LAMBDA式を用いて書き換えたものが下記のものになる
もはや見た目はLisp,業務ではこれ以上に複雑怪奇になっていく,,,

print  [ (lambda x: 'Fizz Buzz' if not x % 5 and not x % 3 else 
           (lambda x:'Fizz' if not x % 3 else  
            (lambda x:'Buzz' if not x % 5)(x) )(x) )(x) for x in range(1, 100)]

で,LAMBDAのメリットってなんなの?

pythonの面倒な正規表現を何とかする

このドメイン正規表現でパースしたい.とする.

  url = 'http://www.mogemoge.com/moge/hoge'
  m   = re.search('//(.*?)/', url).group(1) #<-そもそもurlがドメイン含んでいないっていう

地雷ケースも考慮すると,ワンラインで書けないのだが,lambda を使うとこうなる

  m =  (lambda x:x.group(1) if x else None)( re.search('//(.*?)/', url) )
  • Scala, F#のOptionみたいなことが簡単にできるよ!
  • Optionはあるかもしれないし,ないかもしれない値が存在するときの書き方の一つ

たとえば,[3, None, 1]リストをNoneをのぞいて出力したいです

スカラではこんな感じ

    val hoge:List[Option[String]] = List[Option[String]](Some("3"), None, Some("1"))
    hoge.map {(x) =>
       x match {
         case Some(_x) => println(_x)    
         case _ =>
       }
   }

Scalaのオプションって,強力なんだけど,,,冗長

pythonだとこうなる

 l = [3, None, 1]
 [(lambda x:print(x) if x else None)(x)  for x in l]

Pythonだとすっきりしていいね!
動的型付けのPythonを静的型付けのように使うことの多いPythonではこれは重要なイディオム
そうなのです!lambdaを使うと簡単にScalaの根本をなすOptionを埋め込めることができます

もっとLAMBDA!

たとえばあるあるで,ある変数を0で割ってしまうようなことが発生したらどうする?

print '売り上げ,来客人数,お得意様,お得意様売り上げ'
 revenue, custmer_num, well_custmer_num, well_revenue
print revenue/custmer_num, well_revenue/well_custmer_num

これを例外を考慮して出力したい!
try-except?イケてない.そもそもどっちの割り算でZERO/DEVISION ERRORが発生したかわからない
if分? これもだいぶイケてない.ifで分岐して,同じようなコードを量産する?悪手
LAMBDAがいます!

print revenue/(lambda x:float('inf') if x == 0. else x )(custmer_num), well_revenue/(lambda x:float('inf') if x == 0. else x )(well_custmer_num)

ZERO-DEVISIONになるケースに値をLAMBDAで無限だいにします.すると0が出力され,プロシージャとして例外を吐くことなく継続続行できる