龙空技术网

Python实现自定义容器

驯鹿的古牧 409

前言:

现在我们对“python内置容器对象”大概比较关怀,各位老铁们都想要分析一些“python内置容器对象”的相关资讯。那么小编在网上收集了一些有关“python内置容器对象””的相关知识,希望兄弟们能喜欢,姐妹们快快来了解一下吧!

问题

你想实现一个自定义的类来模拟内置的容器类功能,比如列表和字典。但是你不确定到底要实现哪些方法。

解决方案

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

import collectionsclass A(collections.Iterable):    pass

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

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

你只要实现__iter__()方法就不会报错了。 你可以先试着去实例化一个对象,在错误提示中可以找到需要实现哪些方法:

>>> import collections>>> collections.Sequence()Traceback (most recent call last):File "<stdin>", line 1, in <module>TypeError: Can't instantiate abstract class Sequence with abstract methods \__getitem__, __len__>>>

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

class SortedItems(collections.Sequence):    def __init__(self, initial=None):        self._items = sorted(initial) if initial is not None else []        # Required sequence methods    def __getitem__(self, index):        return self._items[index]    def __len__(self):        return len(self._items)        # Method for adding an item in the right location    def add(self, item):        bisect.insort(self._items, item)items = SortedItems([5, 1, 3])print(list(items))print(items[0], items[-1])items.add(2)print(list(items))

可以看到,SortedItems跟普通的序列没什么两样,支持所有常用操作,包括索引、迭代、包含判断,甚至是切片操作。 这里面使用到了bisect模块,它是一个在排序列表中插入元素的高效方式。可以保证元素插入后还保持顺序。

讨论

使用 collections 中的抽象基类可以确保你自定义的容器实现了所有必要的方法。 并且还能简化类型检查。你的自定义容器会满足大部分类型检查需要,如下所示:

>>> items = SortedItems()>>> import collections>>> isinstance(items, collections.Iterable)True>>> isinstance(items, collections.Sequence)True>>> isinstance(items, collections.Container)True>>> isinstance(items, collections.Sized)True>>> isinstance(items, collections.Mapping)False>>>

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

class Items(collections.MutableSequence):    def __init__(self, initial=None):        self._items = list(initial) if initial is not None else []    # Required sequence methods    def __getitem__(self, index):        print('Getting:', index)        return self._items[index]    def __setitem__(self, index, value):        print('Setting:', index, value)        self._items[index] = value       def __delitem__(self, index):        print('Deleting:', index)        del self._items[index]          def insert(self, index, value):        print('Inserting:', index, value)        self._items.insert(index, value)    def __len__(self):        print('Len')        return len(self._items)

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

>>> a = Items([1, 2, 3])>>> len(a)Len3>>> a.append(4)LenInserting: 3 4>>> a.append(2)LenInserting: 4 2>>> a.count(2)Getting: 0Getting: 1Getting: 2Getting: 3Getting: 4Getting: 52>>> a.remove(3)Getting: 0Getting: 1Getting: 2Deleting: 2>>>

以上只是对 Python 抽象类功能的抛砖引玉。numbers 模块提供了一个类似的跟整数类型相关的抽象类型集合。

标签: #python内置容器对象