《20》デザインパターン〈GoF〉Iterator〈Python 2.x 版〉

実録:はじめてのプログラミング記事一覧
《20》デザインパターンGoFIterator

《著》小粒ちゃん+α《監修》小泉ひよ子とタマゴ倶楽部
2009年2月10日(火)

今日の進捗

  • Language Reference: Data model
  • Python.use(better) -- セミナー研修テキスト
  • 連結リスト課題を「続・ひよ子のきもち」で公開
Comment
本人:野中 逆ポーランド課題(関数版)が完成したので添削をお願いします。クラス版はこれからです。
担当:伊藤/本間 。(^^)

デザインパターンGoFIterator

カタログには〈GoFIterator として紹介されている、デザインパターンを適用した事例を紹介します。

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 を参照する手段には依存しない(情報隠蔽の原則に沿って)抽象的な表現ができるのも〈GoFIterator パターンの効用のひとつです。

《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 文の隘路 - 続・ひよ子のきもち〉《うさぎ》

Last updated♪09/03/11