《32》削除:メソッド pop〈Python 2.x 版〉

実録:はじめてのプログラミング記事一覧
《32》削除:メソッド pop

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

今日の進捗

  • Language Reference: Numeric and Mathematical Modules; functools — Higher order functions and operations on callable objects
  • Python.use(better) -- セミナー研修テキスト
  • 連結リスト課題を「続・ひよ子のきもち」で公開
Comment
本人:野中 リファクタリングの面白さが少し分かりかけて来たような気がします。
担当:伊藤/本間 。(^^)

削除:メソッド pop

組み込み型 list と同様に、メソッド pop を利用して末尾の要素を取り出せると便利です。すると、

def ex():
    s = myList("ABC")
    for i in range(4):
        print "-->",s  ,"\t#",s.__class__.__name__
        r = s.pop()
        print "<--",s,r,"\t#",s.__class__.__name__

>>> ex()
    • > ['A', 'B', 'C'] # myList
<-- ['A', 'B'] C # myList
    • > ['A', 'B'] # myList
<-- ['A'] B # myList
    • > ['A'] # myList
<-- [] A # myList
    • > [] # myList
Traceback (most recent call last): ... raise IndexError,"pop from empty %s"%s IndexError: pop from empty myList

末尾のノードを削除するとともに、削除した値が得られるのが分かります。また、空の連結リストから要素を取り出そうとすると、例外 IndexError を生成して、エラーメッセージを出力します。そこで、

class myList(object):
    ...
    def pop(self):
        prev, node = self.head, self.head.next
        while node:
            if node==self.tail:
                value = node.item
                self.tail = prev
                prev.next = node.next
                del node
                return value
            prev, node = node, node.next
        else:
            s = self.__class__.__name__
            raise IndexError,"pop from empty %s"%s

ノードの末尾に達した node==self.tail とき、その直前のノードの後続 prev.next は、削除したいノードの後続 node.next と同じ値に再設定します。すると、削除したい直前のノードの後に、削除したい直後のノードが続くようになります。そして、指定した要素を含む、オブジェクト node を削除するとともに、その値 value をリターン値にします。

受講者への課題

属性 self.tail が末尾のノードを参照できることを利用して、次のようにすると、

    def pop(self):
        node = self.tail
        value = node.item
        self.tail = prev
        prev.next = node.next
        del node
        return value

このままでは問題が生じます。そこで、新たな属性 self.prev 導入して、以前のノードを参照できるようにしたとき、その長所/短所について考察してくたさい。□

Tips

ここでは、while ブロックに続く処理がなく、return 文によって呼び出し側に制御が戻るので、末尾の処理を else ブロックに記述する必要はありません。ここでは、複雑な後処理が必要になったときに備えて、あらかじめ else ブロックを用意しています。ただし、仕様変更に対するこの先行投資が無駄になる可能性もあります。《りす》□

Last updated♪09/03/20