for と別れる50の方法《04》ジェネレーター yield
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〕の醍醐味を堪能するための準備を行います。
■ 関連記事
- Java プログラマーのための Python 導入ガイド
- 例題で学ぶ Jython/Swing デザインパターン《Jython2.5》改訂版
- ゲームに学ぶ Jython/Swing フレームワーク《Jython2.5》改訂版
- IronPython で学ぶ WPF プログラミングの世界《IronPython2.6》改訂版
何が問題か
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))