8.14 实现自定义容器

    定义了很多抽象基类,当你想自定义容器类的时候它们会非常有用。比如你想让你的类支持迭代,那就让你的类继承 collections.Iterable 即可:

    不过你需要实现 collections.Iterable 所有的抽象方法,否则会报错:

    1. >>> a = A()
    2. Traceback (most recent call last):
    3. File "<stdin>", line 1, in <module>
    4. TypeError: Can't instantiate abstract class A with abstract methods __iter__
    5. >>>

    你只要实现 方法就不会报错了(参考4.2和4.7小节)。

    下面是一个简单的示例,继承自上面Sequence抽象类,并且实现元素按照顺序存储:

    1. class SortedItems(collections.Sequence):
    2. def __init__(self, initial=None):
    3. self._items = sorted(initial) if initial is not None else []
    4.  
    5. # Required sequence methods
    6. def __getitem__(self, index):
    7. return self._items[index]
    8.  
    9. def __len__(self):
    10.  
    11. # Method for adding an item in the right location
    12. def add(self, item):
    13. bisect.insort(self._items, item)
    14.  
    15.  
    16. items = SortedItems([5, 1, 3])
    17. print(list(items))
    18. print(items[0], items[-1])
    19. items.add(2)
    20. print(list(items))

    可以看到,SortedItems跟普通的序列没什么两样,支持所有常用操作,包括索引、迭代、包含判断,甚至是切片操作。

    这里面使用到了 bisect 模块,它是一个在排序列表中插入元素的高效方式。可以保证元素插入后还保持顺序。

    中很多抽象类会为一些常见容器操作提供默认的实现,这样一来你只需要实现那些你最感兴趣的方法即可。假设你的类继承自 collections.MutableSequence ,如下:

    1. class Items(collections.MutableSequence):
    2. def __init__(self, initial=None):
    3. self._items = list(initial) if initial is not None else []
    4.  
    5. # Required sequence methods
    6. def __getitem__(self, index):
    7. return self._items[index]
    8.  
    9. def __setitem__(self, index, value):
    10. print('Setting:', index, value)
    11. self._items[index] = value
    12.  
    13. def __delitem__(self, index):
    14. print('Deleting:', index)
    15. del self._items[index]
    16.  
    17. def insert(self, index, value):
    18. print('Inserting:', index, value)
    19. self._items.insert(index, value)
    20.  
    21. def __len__(self):
    22. print('Len')
    23. return len(self._items)

    如果你创建 Items 的实例,你会发现它支持几乎所有的核心列表方法(如append()、remove()、count()等)。下面是使用演示:

    本小节只是对Python抽象类功能的抛砖引玉。 模块提供了一个类似的跟整数类型相关的抽象类型集合。可以参考8.12小节来构造更多自定义抽象基类。