4.4 容器和集合
除了内置的容器类之外,collections模块也定义许多集合。这些容器类包括namedtuple()、deque、ChainMap、Counter、OrderedDict和defaultdict。所有这些类都是基于抽象基类定义类的例子。
下面是在命令行中显式集合是否支持一个特定方法的快捷方式。
>>>isinstance( {}, collections.abc.Mapping )
True
>>>isinstance(collections.defaultdict(int), collections.abc.Mapping)
True
我们可以检查简单的dict类,看它是否遵循基本的映射协议,并支持必需的方法。
我们可以检查defaultdict集合,确认它也是一种映射。
当自定义容器的时候,可以不用这样正式的方法。我们可以创建一个包含所有正确的特殊方法的类。但是,不用正式声明这个类为某种容器。
使用正确的抽象基类作为我们程序中自定义类的基类显得更清晰也更可靠,额外的形式化声明有以下两个优点。
- 对于读(和有可能在使用或者维护)我们代码的人,这样的声明清晰地表达了我们设计这个类的意图。当我们继承自collections.abc.Mapping时,我们就已经很清晰地表达了这个类应该被如何使用。
- 这样的声明能够对错误诊断提供一些支持。如果没有正确地实现所有必需的方法,那么就会无法创建这个抽象基类的实例。如果因为无法创建对象的实例而使单元测试失败,就说明这是一个必须修复的大问题。
内置容器的完整图谱都是用抽象基类来表示的。底层的特性包括Container、Iterable和Sized。而它们同时也是高级构造过程的一部分。它们需要一些特殊方法,分别是contains()、iter()和len()。
高级的特性包括以下几个部分。
- Sequence和MutableSequence:它们是list和tuple的抽象基类,具体的序列实现还包括bytes和str。
- MutableMapping:这是dict的抽象基类,它扩展了Mapping类,但是没有内置具体的实现。
- Set和MutableSet:它们是frozenset和set的抽象基类。
这些特性允许我们创建新的类,扩展现有的类并且能够使之与Python内置特性的集成变得清晰、流畅。
在第6章“创建容器和集合”中,我们会详细探讨容器和集合的细节。
