for と別れる50の方法《04》ジェネレーター yield

記事一覧if 篇for 篇配列 篇

Python.use(better) # OOP への道 《Python3.1, Jython2.5.0, IronPython2.6.x》
ジェネレーター yield

《著》真樹育未・後藤いるか・小粒ちゃん《監修》小泉ひよ子とタマゴ倶楽部
第0版♪1988/10/12 ● 第1版♪1993/05/23 ● 第2版♪2003/05/25

■ 概要

for 文はいくつかの問題を抱え、OOP を実践するときの「障害」になります。

伝統的なC言語風の for 文や悪名高い switch 文、配列の呪縛から解かれ、オブジェクト指向プログラミング〔OOP〕の醍醐味を堪能するための準備を行います。

何が問題か

OOP の「障害」になる for 文の問題点を明らかにするために、K&R を離れて、別の事例を紹介します。

《Note》Python にも for 文はあります。しかし、これはC言語風の for 文とは「異質」のものです。C言語における while/for の違いを同義語とするなら、Python の for は、同音異義語(似て非なるもの)のようなものです。

イテレーターを導入する

■ 特殊メソッド __iter__
class Node(object):
    def __init__(self, item=None):
        self.item = item
        self.next = None
        
class LinkedList(object):
    def __init__(self, s):
        self.tail = self.head = Node()
        for e in s:
            self.append(e)

    def append(self, e):
        self.tail.item = e
        self.tail.next = Node()
        self.tail = self.tail.next

    def __iter__(self):
        e = self.head
        while e.next:
            yield e.item
            e = e.next

メソッド __iter__ は、基本構文 for..in などに呼応して、各要素を参照する手段(イテレーター)を提供します。yield 文を利用すると、各要素の取扱い(処理済/未処理)が容易になります。すると、次のように、

    def __repr__(self):
        s = []
        for e in self:
            s.append(e.item)
        return "%s(%s)"%(self.__class__.__name__,",".join(s))

Tips:

》作業中です《

Last updated♪2009/07/05

class LinkedList(Collection):
    def do(self, f):
        for e in self:
            f(e)        

    def collect(self, f):
        return [f(e) for e in self]

    def select(self, f):
        return [e for e in self if f(e)]

    def detect(self, f):
        for e in self:
            if f(e): return e

    def inject(self, f, v):
        s = v
        for e in self:
            s = f(s, e)
        return s


class LinkedList(object):

    def __repr__(self):
        s = []
        e = self.head
        while e.next:
            s.append(e.item)
            e = e.next
        return "%s(%s)"%(self.__class__.__name__,",".join(s))