《20》デザインパターン〈GoF〉Iterator《Python3.0》
実録:はじめてのプログラミング《Python3.0》
デザインパターン〈GoF〉Iterator
■ 概要
デザインパターンを学習するための題材として、連結リストを作成します。
組み込み型 list と同等の機能を実現することで、その理解を深めます。list を利用できる状況ならいつでも、これから作成するクラス myList で代用できることを目指します。
《Note》JPython1.1.x/Jython2.1.x 用に作成したセミナー課題を、Jython2.5 で再構成しました。
■ 関連記事
デザインパターン〈GoF〉Iterator
カタログには〈GoF〉Iterator として紹介されている、デザインパターンを適用した事例を紹介します。
class myList(object): ... def __iter__(self): node = self.head.next while node: yield node.item node = node.next
メソッド __iter__ は、基本構文 for..in などに呼応して、各要素を参照する手段(イテレーター)を提供します。yield 文を利用すると、各要素の取扱い(処理済/未処理)が容易になります。すると、次のように、
## ---------------------------------------- ver.1 def __str__(self): s = node = self.head.next while node: s.append(repr(node.item)) node = node.next return "[{0}]".format(", ".join(s)) ## ---------------------------------------- ver.2 def __str__(self): s = for e in self: s.append(repr(e)) return "[{0}]".format(", ".join(s))
ver.1 と比べて、より洗練されたコードを記述できます。ただ self と記述するだけで、各要素 e を参照する手段には依存しない(情報隠蔽の原則に沿って)抽象的な表現ができるのも〈GoF〉Iterator パターンの効用のひとつです。
《Note》メソッド __iter__ を用意しないと、次のように、
Traceback (most recent call last): ... for e in self: TypeError: 'myList' object is not iterable例外 TypeError を生成して、反復処理には適しません。なぜなら、myList はまだ、反復処理に呼応するための準備が整っていないからです。
def ex(): # s = list() s = myList() for e in "ABC": s.append(e) print(s,"\t#",s.__class__.__name__) for e in s: print(e,end=" ") >>> ex() ['A', 'B', 'C'] # myList A B C
基本構文 for..in を利用して、連結リスト s の各要素 e を参照できます。また、コメントにあるように、クラス myList に代えて、組み込み型 list を利用しても、次のように、
>>> ex()
['A', 'B', 'C'] # list
A B C
同様の結果が得られます。実行時に属性 .__class__.__name__ を参照しているので、その違いが分かります。
Tips
情報隠蔽の原則に沿って、その実現方法(how)に依存しない、抽象表現(what)が可能になります。利用者は、組み込み型 list とクラス myList との違いを意識する必要はありません。また、その機能をどのように実現しているかを知る必要もなくなります。すると、コードの再利用性が向上します。
⇒ for と別れる50の方法《1》for 文の隘路 - 続・ひよ子のきもち
》作業中です《