Python.use(better,"K&R")《25》switch(3)脱・ハードコーディング
|記事一覧|《こちらに移動中です》2007年10月31日 (水)
Python.use(better, follow=”K&R”) # for novice
《25》switch(3)脱・ハードコーディング《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
《承前》
def digit(self, c) : self.ndigit[int(c)] += 1 def white(self, *c): self.nwhite += 1 def other(self, *c): self.nother += 1
メソッド digit/white/other は、数字/空白文字/その他の出現頻度を求めます。文字 c が出現するたびに、各カウンター変数 ndigit/nwhite/nother の値が1つずつ増加します。
def scan(self): for line in file(self.name): for e in line: self.switch.get(e, self.other)(e)
メソッド scan は、指定した名前 self.name のファイルに含まれる文字の出現頻度を求めます。辞書 self.switch の中から、文字キー e に対応するメソッドを獲得 get します。キーが存在しないときには、規定値としてメソッド self.other が得られます。これが、switch 文の default: に相当します。すると、実引数には文字 e が与えられ、適切なメソッドを呼び出します。
《Note》switch 文をオブジェクトに
基本的な戦略は、switch 文が必要になる状況(抽象表現)を、オブジェクトとして表現(具象化)することです。□
def __str__(self): s = "digits =" for e in self.ndigit: s += " %d"%e s += ", white space = %d, other = %d"%( self.nwhite, self.nother) return s
メソッド __str__ は、インスタンスに固有の文字列表現を規定します。
ここまでに示した手法は、switch 文の代用表現を示しただけです。そのため、記述したコードも、switch 文と比べて冗長になりがちです。しかし、両者には、決定的なアプローチの違いがあります。それが、次に示す動的な問題解決です。
name = "src/symbol.py" counter = Occurrence(name) print counter counter.switch["#"] = counter.white counter.rescan() print counter counter.switch["0"] = counter.other counter.rescan() print counter
このコードの断片を実行すると、次のような出力結果が得られます。
digits = 19 20 62 58 8 12 19 19 19 19, white space = 397, other = 1379 digits = 19 20 62 58 8 12 19 19 19 19, white space = 406, other = 1370 digits = 0 20 62 58 8 12 19 19 19 19, white space = 406, other = 1389
まず、規定した文字だけを対象に出現頻度を求めます。次に、新たに文字 "#" を空白文字の仲間に加えて、再び出現頻度を求めます。すると、空白文字とその他の出現頻度が増減します。さらに、数字 "0" をその他の文字の仲間に加えて、再び出現頻度を求めます。すると、数字とその他の出現頻度が増減します。このように、インスタンスごとに 異なる文字を対象としたり、実行時にその対象を変更したり、状況に応じて挙動を変えたいときには便利です。switch 文に象徴されるハードコーディングでは、動的な問題解決にはうまく対処できません。
def rescan(self, name=None): if name: self.name = name self.nwhite = 0 self.nother = 0 self.ndigit = [0]*10 self.scan()
関数 rescan は、値を再設定して、再び scan() で文字の出現頻度を求めます。
《ひよ子のきもち♪2007/09/28》
《余録》
アナログ思考からディジタル思考へ
受講者の中には(勘のいい読者のみなさんの中に も)switch を必要としてきた場面が、三項演算子を必要とする状況と似ていることに気付いた方もいます。実際に、三項演算子の代替案となる戦略は、ここで紹介した戦略 の特殊な場合にすぎないことが分かります。つまり、case/default を1つずつ持つ switch と等価なのです。伝統的な SP から OOP へと脱皮したいと願うなら、それは old-timer だけでなく、Java/C# プログラマーにとって「対岸の火事」とばかりも言っていられない状況です。アナログ思考(Java/C#)からディジタル思考(Ruby/Python) へと、際物でない本物指向の OOP の扉を叩くなら、今がその好機です。switch 文の回避に関する広範な論議は、Smalltalk が参考になります。もちろん、純粋なオブジェクト指向を支援する Smalltalk の開発環境下では、goto/switch はありません。なぜなら、必要ないからです。
アジャイル開発向きの言語仕様
要求仕様が確定して、将来の変更が 起こりそうもない状況では、switch 文は強力な武器となります。しかし、アジャイル開発のもとでは、要求仕様が確定しない状況でも、開発を先行させるのが常です。さもないと、生き残りを懸け た競争の激しい市場では、自然淘汰されかねません。従来は、要求仕様が確定しないことを納期遅れの言い訳にもできました。ディジタル世代のソフトウェア開 発の現場では、もうそのような言い訳は通用しません。逆に、アリバイ工作に終止するなら、switch 文は、打ってつけの口実になるかもしれません。オブジェクト`指向`だけでなく、その`思考`回路もハードからソフトへと変革したいモノですね。
==================================
後藤いるか 著 ◆ 監修:小泉ひよ子とタマゴ倶楽部