8. BinaryNodeクラスを
シーケンスのように振る舞わせる
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
# Returns (found, count)
def __getitem__(self, index):
found, _ = self._search(0, index)
if not found:
raise IndexError('Index out of range')
return found.value
9. BinaryNodeクラスを
シーケンスのように振る舞わせる
• IndexableNode
– 通常の二分木として構築できる
– Listのようにアクセスできる
print('LRR =', tree.left.right.right.value) #LRR = 7
print('Index 0 =', tree[0]) #Index 0 = 2
print('Index 1 =', tree[1]) #Index 1 = 5
print('11 in the tree?', 11 in tree) #11 in the tree? True
print('17 in the tree?', 17 in tree) #17 in the tree? False
print('Tree is', list(tree)) #Tree is [2, 5, 6, 7, 10, 11, 15]
11. 独自のコンテナ型を定義するのは困難
• 他にも特別なメソッドの定義が必要
– countやindexというメソッドが足りない
• collections.abcモジュール
– 典型的なメソッドをすべて提供する抽象基底クラス
– 必要なメソッドの実装がないと教えてくれる
from collections.abc import Sequence
class BadType(Sequence):
pass
foo = BadType()
>>>
TypeError: Can’t instantiate abstract class BadType with abstract methods __getitem__,
__len__
12. 独自のコンテナ型を定義するのは困難
try:
from collections.abc import Sequence
class BadType(Sequence):
pass
foo = BadType()
except:
logging.exception('Expected')
else:
assert False
>>>
TypeError: Can’t instantiate abstract class BadType with abstract methods __getitem__,
__len__
13. collections.abc
• 抽象基底クラスに必要な全てのメソッドを実装
– 追加メソッドが提供される(indexやcountなど)
– 複雑な型(SetやMutableMapping等)で特に有用
– 実装が必要な特殊メソッドの個数が膨大
class BetterNode(SequenceNode, Sequence):
pass
tree = BetterNode(...)
print('Index of 7 is', tree.index(7)) #Index of 7 is 3
print('Count of 10 is', tree.count(10)) #Count of 10 is 1