Java.use(better, Python)《14》for と別れる50の方法(その伍)

記事一覧《こちらに移動中です》2006年6月22日 (木)

Java.use(better, Python)  # Stairway to Real Agile World

《14》for と別れる50の方法(その伍)《Jython2.5.0》

《著》後藤いるか・河野かえる・河野めだか・伊藤うさぎ・小粒ちゃん+∞《監修》小泉ひよ子とタマゴ倶楽部
第1版♪2003/05/23

■ 概要

継承の概念を実現するのに、いくつかの方法があります。そのひとつが、新しいクラスを定義した後で、そのインスタンスに固有のメソッドを再定義するというものです。

継承には、
 (1)構造継承
 (2)機能継承
 (3)プロトコル継承
があって、さらに(2)機能継承は、次の3つに分類されます。
 (2a)親子関係にあるクラス間の継承
 (2b)親子関係にないクラス間の継承
 (2c)クラスとインスタンス間の継承
ともすると、Java/C# などでは、狭義の(2a)に関心が寄せられがちです。しかし、純粋な OOP の世界では、その限りではありません。では、広義の継承は、どのように実現するのでしょうか。

■ 関連記事
  •  

前の記事次の記事

《14》for と別れる50の方法(その伍)

■ 二分木の例

単純な二分木を使って、for 文を任意のインスタンスに適用する事例を紹介します。

tree = Tree(0,Tree(1,Tree(2),Tree(3)),Tree(4,Tree(5),Tree(6)))
tree.display()
# -------------------------------- Output --
        +-- 2
    +-- 1
        +-- 3
+-- 0
        +-- 5
    +-- 4
        +-- 6

クラス Tree は、二分木を実現したものです。Tree のインスタンスを生成して、変数 tree に代入します。tree は、いくつかの部分木によって構成されます。式 tree.display() を評価すると、tree の構造を表現した文字列が出力されます。

for node in tree:
  print node*10,
# -------------------------------- Output --
20 10 30 0 50 40 60

for 文を使うと、制御変数 node には、二分木 tree が保持する節が順に代入されます。出力結果を見ると、各節の値を 10 倍したものが、空白で区切られているのが分ります。

class Tree:
  items = None
    
  def __getitem__(self,index):
    if self.items == None:
      self.items = self.inOrder()
    return self.items._list[index]

メソッド関数 __getitem__ を再定義すると、任意のインスタンスに対して、[ ] を伴う添字付けが可能となります。また、インスタンスを構成する各要素を参照するのに、for 文が使えるようになります。引数 index には、各要素を参照するための添字が渡されます。ここでは、インスタンス属性 self.items には、間順走査によって得られた節を要素とする、リスト self.inOrder() が代入されています。そして、添字 index によって参照されるリスト内の要素を、リターンオブジェクトとします。

《Note》特殊メソッド:__getitem__
 __getitem__(self, key)

式 self[key] を評価するときに実行されるコードを実現します。シーケンス型に対して、キーとして認められるのは、整数およびスライスです。□

class Tree:
  def inOrder(self):
    l = self.left. inOrder()
    v = OCL_Sequence([self.value])
    r = self.right.inOrder()
    result = l.union(v).union(r)        
    assert self._post_asSequence(result)
    return result

※ OCL_Sequence の詳細については、関連する連載記事を参照してください。□

print ">>> 3:", 3 in tree
print ">>> 7:", 7 in tree
# -------------------------------- Output --
>>> 3: True
>>> 7: False

__getitem__ を再定義するだけで、任意のインスタンスに対して、演算子 in を伴う論理演算が可能となります。ここでは、3 および 7 を値に持つ節が存在するかを判定しています。出力結果を見ると、3 を値に持つ節が存在するので True が、7 を値に持つ節が存在しないので False が、それぞれ得られているのが分ります。

print ">>>", t
print "pre :", t.preOrder()
print "in  :", t.inOrder()
print "post:", t.postOrder()
# -------------------------------- Output --
>>> 0(1(2(,),3(,)),4(5(,),6(,)))
pre : Sequence {0, 1, 2, 3, 4, 5, 6}
in  : Sequence {2, 1, 3, 0, 5, 4, 6}
post: Sequence {2, 3, 1, 5, 6, 4, 0}

確かに、for 文が使えるのは便利です。しかし、間順走査だけに限定されるのでは不便です。他に、前順走査、後順走査、深さ優先、幅優先など、多様な制御構造が期待される状況でも、その中のひとつだけを for 文に規定することになります。

class Tree:
  def preOrder(self):
    l = self.left. preOrder()
    v = OCL_Sequence([self.value])
    r = self.right.preOrder()
    result = v.union(l).union(r)        
    assert self._post_asSequence(result)
    return result

メソッド関数 preOrder は、二分木の各節を前順走査します。

class Tree:
  def postOrder(self):
    l = self.left. postOrder()
    v = OCL_Sequence([self.value])
    r = self.right.postOrder()
    result = l.union(r).union(v)        
    assert self._post_asSequence(result)
    return result

メソッド関数 postOrder は、二分木の各節を後順走査します。

t = Tree("sunday",
        Tree("monday",
          Tree("tuesday"),
          Tree("wednesday")),
        Tree("thursday",
          Tree("friday"),
          Tree("saturday")))
s = t.asSequence()
print ">>>", s
print s.collect(lambda e: e.capitalize())
print s.select(lambda e: e.startswith("s"))
print s.reject(lambda e: len(e)>6)
# -------------------------------- Output --
        +-- tuesday
    +-- monday
        +-- wednesday
+-- sunday
        +-- friday
    +-- thursday
        +-- saturday
>>> Sequence {'tuesday', 'monday', 'wednesday', 'sunday', 'friday', 'thursday', 'saturday'}
Sequence {'Tuesday', 'Monday', 'Wednesday', 'Sunday', 'Friday', 'Thursday', 'Saturday'}
Sequence {'sunday', 'saturday'}
Sequence {'monday', 'sunday', 'friday'}

メソッド関数 asSequence を使うと、コレクションフレームワークで規定された、より柔軟な記述ができるようになります。しかし、これらはシーケンスに対する操作であって、二分木に対する制御構造を規定したものではありません。for 文と別れるには、さらにもうひと工夫が必要です。
==================================
後藤いるか+河野めだか 著 ◆ 監修:小泉ひよ子とタマゴ倶楽部

Last updated♪2009/08/02