YAMAGUCHI::weblog

海水パンツとゴーグルで、巨万の富を築きました。カリブの怪物、フリーアルバイター瞳です。

switch-case文に関する考察

いまPythonでshellスクリプトを書いてちょっと勉強をしています。shellコマンドはシンプルなので作るにはいい題材だし、挙動それ自体はいい勉強になるんですよね。で、shellコマンドのオプションを処理するときに、Cとかではgetopt()とか使ったりしますが、ちょこっと作るときにはswitchなんか使ってみたりするわけです。

で、話はPython。いま作っているスクリプトでもオプションは受け付けたいです。しかしPythonにはswitch文がないです。じゃあどうやってそれを実現するかといったら、2つ方法があるわけで。

  1. if-elif-elseで対応する
  2. 辞書型で対応する

前者の場合は自明です。case文を一つ一つif(elif, else)ブロックに対応させてあげればいいという話。しかしそれはスマートじゃありません。そこで辞書型を使います。
Pythonの場合関数それ自体もオブジェクトですので、辞書にはオプションと関数のリストを作ります。

def foo_func():
    ...statements...

def bar_func():
    ...statements...

def fizz_func():
    ...statements...

def no_match():
    ...default statements...

options = {
    'foo' : foo_func,
    'bar' : bar_func,
    'fizz' : fizz_func
}

# 典型的な方法
options.get(string, no_match)()

# 確実に値が返ってくるとき
options[string]()

さらにオプションとかを考えるなら、こんなこともできる。

import sys

argvs = sys.argv

def foo_option(vars):
    for v in vars:
        print 'foo -- ' + v

def bar_option(vars):
    for v in vars:
        print 'bar -- ' + v

def no_match(vars):
    print "see help"

options = {
    'foo' : foo_option,
    'bar' : bar_option
}

options.get(argvs[1], no_match)(argvs[2:])

ただし、実行速度という意味ではswitch文があった方が速かったのかもしれない。

しかし上記にあるような状況で行わなければいけない判断はあるだろうか。Pythonはそういった実行速度は捨てて、よりオブジェクト指向なプログラミングを目指したのかもしれない。(そういう点ではRubyの方が一貫しているが)