Python.use(better,"K&R")《23》switch(1)なぜ switch は不要か
|記事一覧|《こちらに移動中です》2007年10月31日 (水)
Python.use(better, follow=”K&R”) # for novice
《23》switch(1)なぜ switch は不要か《Jython2.5.0》
■ 概要
goto と並んで悪名高いのが switch です。構造化プログラミングには心強い味方であり、old-timer にも根強い人気ですが、オブジェクト指向プログラミングには、逆に switch が手枷足枷となります。
この連載では、K&R の名著 "The C Programming Language" を読み解きながら、Python によるオブジェクト指向プログラミングへの扉を開きます。
■ 関連記事
- INDEX〈Python〉
- Java™ Programming Language, The, 4th Edition《Contents》
- 2007年8月18日《21》switch 文は、百害あって一利なし《前篇》
- 2007年8月25日《22》switch 文は、百害あって一利なし《後篇》
- 2007年7月 9日《11》三項演算子 ?: に代わるもの★
なぜ switch が(必要)ないのか
goto と並んで悪名高いのが switch ですが、伝統的な構造化プログラミング〔SP〕を好む old-timer には、変わらず根強い人気があるのも事実です。
Python では、オブジェクト指向プログラミング〔OOP〕はオプションであり、それを強要されたりはしません。しかし、洗練された OOP を習得したいなら、goto/switch への未練を断ち切れるかが鍵になります。
よく「Python には switch もないのか」という話を耳にします。ここで「Python にはなぜ switch が必要ないのか」を理解するのが、OOP への「近道」です。
「2007 年問題」が現実になり、高齢化社会への扉が開かれた今だから old-timer への配慮なのか、三項演算子を連想させる構文が導入されました。近い将来、Python にも switch が導入されるなら、old-timer には朗報かもしれません。しかし、それは OOP を習得する機会を逃すだけでなく、永遠にその扉を閉ざしかねません。
【K&R, p.58】"The switch statement is a multi-way decision that tests whether an expression matches one of a number of constant integer values ..." とあるように「switch 文は(コンパイル時に)確定できる条件下で処理を選択したい」ときには便利です。そのため、伝統的な switch を用いる戦略は「ハードコーディング」の典型とも言えます。
【K&R, p.59】 #includemain() /* count digits, white space, others */ { int c, i, nwhite, nother, ndigit[10]; nwhite = nother = 0; for (i = 0; i < 10; i++) ndigit[i] = 0: while ((c = getchar()) != EOF) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ndigit[c-'0']++; break; case ' ': case '\n': case '\t': nwhite++; break; default: nother++; break; } } printf("digits ="); for (i = 0; i < 10; i++) printf(" %d", ndigit[i]); printf(", white space = %d, other = %d\n", nwhite, nother); return 0; }
K&R の事例では、入力された文字を判定するために、switch 文が必要です。伝統的な SP では重宝される switch 文も、純粋な OOP ではそれが手枷足枷になります。switch 文への未練を断ち切れたら、また一歩 OOP の神髄へと近づけます。switch 文の未練を断つ方法の中から、今回は、辞書 map を使う事例を紹介します。他の方法は、関連記事で紹介します。
name = "src/symbol.py" counter = {} for line in file(name): for e in line: if e in counter: counter[e] += 1 else: counter[e] = 1
先を急ぐ前に、文字の出現頻度を求めるだけなら、話は簡単です。ここでは、標準入力の代わりに、任意のファイルに含まれる文字を対象にします。ここで "symbol.py" とあるのは、Python 2.5 のリリースに含まれるものです。Python には、組み込み型 bag はありませんが、もしあると話は簡単です。
counter = bag() for line in file(name): for e in line: counter.add(e)
単に、メソッド add を利用して要素(任意の文字)を追加するだけです。ここで bag とあるのは、Smalltalk/OCL の規定に準拠したものです。詳細は、関連記事で紹介します。
《ひよ子のきもち♪2007/09/26》
==================================
後藤いるか 著 ◆ 監修:小泉ひよ子とタマゴ倶楽部