《32》削除:メソッド pop〈Python 3.0 版〉

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

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

削除:メソッド pop

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

def ex_pop():
    X = 's = myList("ABC"); s'
    print(">>>",X)
    eval(compile(X,"","single"))
    for i in range(4):
        X = 'r = s.pop(); print(s,repr(r))'
        print(">>>",X)
        eval(compile(X,"(x_x)","single"))

その動作(仕様)を確認すると、

>>> ex_pop()
>>> s = myList("ABC"); s
['A', 'B', 'C']
>>> r = s.pop(); print(s,repr(r))
['A', 'B'] 'C'
>>> r = s.pop(); print(s,repr(r))
['A'] 'B'
>>> r = s.pop(); print(s,repr(r))
[] 'A'
>>> r = s.pop(); print(s,repr(r))
Traceback (most recent call last):
...
    raise IndexError("pop from empty %s"%s)
IndexError: pop from empty myList

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

実現:メソッド pop

メソッド list.pop に準拠したものを実現します〈図解〉。

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