《20》デザインパターン〈GoF〉Iterator〈Python 2.x 版〉
実録:はじめてのプログラミング《記事一覧》
《20》デザインパターン〈GoF〉Iterator
関連記事
今日の進捗
Comment | |
---|---|
本人:野中 | 逆ポーランド課題(関数版)が完成したので添削をお願いします。クラス版はこれからです。 |
担当:伊藤/本間 | 。(^^) |
デザインパターン〈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 文を利用すると、各要素の取扱い(処理済/未処理)が容易になります。すると、次のように、
class myList(object): ... def __str__(self): # ver.2 s = [] for e in self: s.append(repr(e)) return "[%s]"%", ".join(s)
for 文を使って(ver.1 と比べて)より簡潔に表現できるのが分かります。各要素 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, >>> 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 文の隘路 - 続・ひよ子のきもち〉《うさぎ》