almost 3 years ago

Inherit from collections.abc for Custom Container Types

這個條款主要講得是 collections.abc 這個 module 的東西,注意在 Python 3.3 之前的版本是 collections

collections.abc 裡頭的 abstract classes 的作用是讓開發者方便地開發自己的 container ,例如 list。一般情況下繼承 list 當然沒問題,但是當資料結構比較複雜時就需要自己自幹,例如 list 有許多 methods ,要一一實現有點麻煩。

下面程式中 SequenceNode 是想要擁有 list 介面的 binary tree。

class BinaryNode(object):
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right

class IndexableNode(BinaryNode):
    def _search(self, count, index):
        found = None
        if self.left:
            found, count = self.left._search(count, index)
        if not found and count == index:
            found = self
        else:
            count += 1
        if not found and self.right:
            found, count = self.right._search(count, index)
        return found, count

    def __getitem__(self, index):
        found, _ = self._search(0, index)
        if not found:
            raise IndexError('Index out of range')
        return found.value

class SequenceNode(IndexableNode):
    def __len__(self):
        _, count = self._search(0, None)
        return count

對 SequenceNode 的 instances 做一些 list 常用的操作看起來沒問題

tree = SequenceNode(
    10,
    left=SequenceNode(
        5,
        left=SequenceNode(2),
        right=SequenceNode(
            6, right=SequenceNode(7))),
    right=SequenceNode(
        15, left=SequenceNode(11))
)

print('Index 0 =', tree[0])  # 2

print('11 in the tree?', 11 in tree)  # True

print('Tree has %d nodes' % len(tree)) # 7

但是使用者可能想呼叫諸如 count() 以及 index() 等 list 的 methods ,這時可以使用 collections.abcSequence。子類只要實作 __getitem__ 以及 __len__Sequence 已經提供 count() 以及 index() 了。

from collections.abc import Sequence

class BetterNode(SequenceNode, Sequence):
    pass

tree = BetterNode(
    10,
    left=BetterNode(
        5,
        left=BetterNode(2),
        right=BetterNode(
            6, right=BetterNode(7))),
    right=BetterNode(
        15, left=BetterNode(11))
)

print('Index of 7 is', tree.index(7))
print('Count of 10 is', tree.count(10))
← Effective Python 心得筆記: Item 27 Effective Python 心得筆記: Item 29 and Item 30 →
 
comments powered by Disqus