collections.abc --- 容器的抽象基类

Added in version 3.3: 该模块曾是 collections 模块的组成部分。

源代码: Lib/_collections_abc.py


本模块提供了一些 抽象基类,它们可被用于测试一个类是否提供某个特定的接口;例如,它是否为 hashable 或是否为 mapping 等。

一个接口的 issubclass() 或 isinstance() 测试采用以下三种方式之一。

  1. 新编写的类可以直接继承自某个抽象基类。 该类必须提供所需的抽象方法。 其余混入方法来自于继承并且可在需要时被重写。 其他方法可按需添加:

    class C(Sequence):                      # 直接继承
        def __init__(self): ...             # ABC 所不需要的额外方法
        def __getitem__(self, index):  ...  # 需要的抽象方法
        def __len__(self):  ...             # 需要的抽象方法
        def count(self, value): ...         # 可选覆盖一个混入方法
    
    >>> issubclass(C, Sequence)
    True
    >>> isinstance(C(), Sequence)
    True
    
  2. 已有的类和内置类可被注册为 ABC 的"虚拟子类"。 这些类应当定义完整的 API 包括所有抽象方法和所有混入方法。 这使得用户能依靠 issubclass() 或 isinstance() 测试来确定完整接口是否受到支持。 此规则的例外情况是那些从 API 的其他部分自动推断出来的方法:

    class D:                                 # 无继承
        def __init__(self): ...              # ABC 所不需要的额外方法
        def __getitem__(self, index):  ...   # 抽象方法
        def __len__(self):  ...              # 抽象方法
        def count(self, value): ...          # 混入方法
        def index(self, value): ...          # 混入方法
    
    Sequence.register(D)                     # 注册而非继承
    
    >>> issubclass(D, Sequence)
    True
    >>> isinstance(D(), Sequence)
    True
    

    在这个例子中,D 类不需要定义 __contains__, __iter__ 和 __reversed__,因为 in 运算符, 迭代 逻辑和 reversed() 函数会自动回退为使用 __getitem__ 和 __len__。

  3. 某些简单接口可以根据所需方法是否存在来直接识别 (除非这些方法已被设置为 None):

    class E:
        def __iter__(self): ...
        def __next__(self): ...
    
    >>> issubclass(E, Iterable)
    True
    >>> isinstance(E(), Iterable)
    True
    

    复杂的接口不支持最后这种技术手段因为接口并不只是作为方法名称存在。 接口指明了方法之间的语义和关系,这些是无法根据特定方法名称的存在推断出来的。 例如,知道一个类提供了 __getitem__, __len__ 和 __iter__ 并不足以区分 Sequence 和 Mapping。

Added in version 3.9: 这些抽象类现在都支持 []。 参见 GenericAlias 类型 和 PEP 585。

容器抽象基类

collections 模块提供了以下 ABCs:

抽象基类

继承自

抽象方法

混入方法

Container [1]

__contains__

Hashable [1]

__hash__

Iterable [1] [2]

__iter__

Iterator [1]

Iterable

__next__

__iter__

Reversible [1]

Iterable

__reversed__

Generator [1]

Iterator

send, throw

close, __iter__, __next__

Sized [1]

__len__

Callable [1]

__call__

Collection [1]

Sized, Iterable, Container

__contains__, __iter__, __len__

Sequence

Reversible, Collection

__getitem__, __len__

__contains__, __iter__, __reversed__, index 和 count

MutableSequence

Sequence

__getitem__, __setitem__, __delitem__, __len__, insert

继承了 Sequence 的方法以及 append, clear, reverse, extend, pop, remove 和 __iadd__

ByteString

Sequence

__getitem__, __len__

继承的 Sequence 方法

Set

Collection

__contains__, __iter__, __len__

__le__, __lt__, __eq__, __ne__, __gt__, __ge__, __and__, __or__, __sub__, __rsub__, __xor__, __rxor__ 和 isdisjoint

MutableSet

Set

__contains__, __iter__, __len__, add, discard

继承自 Set 的方法以及 clear, pop, remove, __ior__, __iand__, __ixor__,和 __isub__

Mapping

Collection

__getitem__, __iter__, __len__

__contains__, keys, items, values, get, __eq__ 和 __ne__

MutableMapping

Mapping

__getitem__, __setitem__, __delitem__, __iter__, __len__

继承自 Mapping 的方法以及 pop, popitem, clear, update,和 setdefault

MappingView

Sized

__init__, __len__ 和 __repr__

ItemsView

MappingView, Set

__contains__, __iter__

KeysView

MappingView, Set

__contains__, __iter__

ValuesView

MappingView, Collection

__contains__, __iter__

Awaitable [1]

__await__

Coroutine [1]

Awaitable

send, throw

close

AsyncIterable [1]

__aiter__

AsyncIterator [1]

AsyncIterable

__anext__

__aiter__

AsyncGenerator [1]

AsyncIterator

asend, athrow

aclose, __aiter__, __anext__

Buffer [1]

__buffer__

附注

多项集抽象基类 -- 详细描述

class collections.abc.Container

提供了 __contains__() 方法的抽象基类。

class collections.abc.Hashable

提供了 __hash__() 方法的抽象基类。

class collections.abc.Sized

用于提供 __len__() 方法的类的 ABC

class collections.abc.Callable

用于提供 __call__() 方法的类的 ABC

有关如何在类型标注中使用 Callable 的详细信息请参阅 标注可调用对象。

class collections.abc.Iterable

用于提供 __iter__() 方法的类的 ABC

isinstance(obj, Iterable) 检查能侦测到被注册为 Iterable 或者具有 __iter__() 方法的类,但它不能侦测到使用 __getitem__() 方法进行迭代的类。 确定一个对象是否为 iterable 的唯一可靠方式是调用 iter(obj)。

class collections.abc.Collection

针对有大小的可迭代容器类的 ABC。

Added in version 3.6.

class collections.abc.Iterator

提供了 __iter__() 和 __next__() 方法的抽象基类。参见 iterator 的定义。

class collections.abc.Reversible

用于同时提供了 __reversed__() 方法的可迭代类的 ABC

Added in version 3.6.

class collections.abc.Generator

用于实现了 PEP 342 中定义的协议的 generator 类的 ABC,它通过 send(), throw() 和 close() 方法对 迭代器 进行了扩展。

有关在类型标注中使用 Generator 的详细信息请参阅 标注生成器和协程。

Added in version 3.5.

class collections.abc.Sequence
class collections.abc.MutableSequence
class collections.abc.ByteString

只读的与可变的 序列 的抽象基类。

实现注意事项:某些混入方法,如 __iter__(), __reversed__() 和 index(),会重复调用下层的 __getitem__() 方法。 因此,如果 __getitem__() 被实现为常数级访问速度,则混入方法的性能将为线性级;但是,如果下层的方法是线性的(例如链表就是如此),则混入方法的性能将为平方级并可能需要被重写。

index(value, start=0, stop=None)

返回首个 value 的索引。

如果该值不存在则会引发 ValueError。

对 start 和 stop 参数的支持是可选项,但建议使用。

在 3.5 版本发生变更: index() 方法获得对 stop 和 start 参数的支持。

从 3.12 版起已弃用,将在 3.17 版中移除: ByteString ABC 已被弃用。

使用 isinstance(obj, collections.abc.Buffer) 来测试 obj 是否在运行时实现了 缓冲区协议。 要用于类型标注,则使用 Buffer 或是显式指明你的代码所支持的类型的并集 (例如 bytes | bytearray | memoryview)。

ByteString 原本是想作为 bytes 和 bytearray 的超类型的抽象基类提供。 不过,由于该 ABC 从未有过任何方法,知道一个对象是 ByteString 的实例并不能真正告诉你有关该对象的任何有用信息。 其他常见缓冲区类型如 memoryview 同样不能被当作是 ByteString 的子类型(无论是在运行时还是对于静态类型检查器)。

请参阅 PEP 688 了解详情。

class collections.abc.Set
class collections.abc.MutableSet

用于只读和可变 集合 的 ABC。

class collections.abc.Mapping
class collections.abc.MutableMapping

只读的与可变的 映射 的抽象基类。

class collections.abc.MappingView
class collections.abc.ItemsView
class collections.abc.KeysView
class collections.abc.ValuesView

映射、条目、键和值的 视图 的抽象基类。

class collections.abc.Awaitable

针对 awaitable 对象的 ABC,它可被用于 await 表达式。 自定义实现必须提供 __await__() 方法。

协程 对象和 Coroutine ABC 的实例都是这个 ABC 的实例。

备注

在 CPython 中,基于生成器的协程 (使用 @types.coroutine 装饰的 生成器) 都是 可等待对象,即使它们没有 __await__() 方法。 对它们使用 isinstance(gencoro, Awaitable) 将返回 False。 请使用 inspect.isawaitable() 来检测它们。

Added in version 3.5.

class collections.abc.Coroutine

用于 coroutine 兼容类的 ABC。 实现了如下定义在 协程对象 里的方法: send(), throw() 和 close()。 自定义实现还必须实现 __await__()。 所有的 Coroutine 实例同时也是 Awaitable 的实例。

备注

在 CPython 中,基于生成器的协程 (使用 @types.coroutine 装饰的 生成器) 都是 可等待对象,即使它们没有 __await__() 方法。 对它们使用 isinstance(gencoro, Coroutine) 将返回 False。 请使用 inspect.isawaitable() 来检测它们。

有关在类型标注中使用 Coroutine 的详细信息请参阅 标注生成器和协程。 类型形参的型变与顺序与 Generator 的相对应。

Added in version 3.5.

class collections.abc.AsyncIterable

针对提供了 __aiter__ 方法的类的 ABC。 另请参阅 asynchronous iterable 的定义。

Added in version 3.5.

class collections.abc.AsyncIterator

提供了 __aiter__ 和 __anext__ 方法的抽象基类。参见 asynchronous iterator 的定义。

Added in version 3.5.

class collections.abc.AsyncGenerator

针对实现了在 PEP 525 和 PEP 492 中定义的协议的 asynchronous generator 类的 ABC。

有关在类型标注中使用 AsyncGenerator 的详细信息请参阅 标注生成器和协程。

Added in version 3.6.

class collections.abc.Buffer

针对提供 __buffer__() 方法的类的 ABC,实现了 缓冲区协议。 参见 PEP 688。

Added in version 3.12.

例子和配方

ABC 允许我们询问类或实例是否提供特定的功能,例如:

size = None
if isinstance(myvar, collections.abc.Sized):
    size = len(myvar)

有些 ABC 还适用于作为混入类,这可以更容易地开发支持容器 API 的类。 例如,要写一个支持完整 Set API 的类,只需要提供三个下层抽象方法: __contains__(), __iter__() 和 __len__()。 ABC 会提供其余的方法如 __and__() 和 isdisjoint():

class ListBasedSet(collections.abc.Set):
    ''' 空间重于速度并且不要求集合元素可哈希的
        替代性集合实现。 '''
    def __init__(self, iterable):
        self.elements = lst = []
        for value in iterable:
            if value not in lst:
                lst.append(value)

    def __iter__(self):
        return iter(self.elements)

    def __contains__(self, value):
        return value in self.elements

    def __len__(self):
        return len(self.elements)

s1 = ListBasedSet('abcdef')
s2 = ListBasedSet('defghi')
overlap = s1 & s2            # 自动支持 __and__() 方法

当把 Set 和 MutableSet 用作混入类时需注意:

  1. 由于某些集合操作会创建新的集合,默认的混入方法需要一种根据 iterable 创建新实例的方式。 假定类构造器具有 ClassName(iterable) 形式的签名。 该假设被提取到一个名为 _from_iterable() 的内部 classmethod 中,该方法会调用 cls(iterable) 来产生一个新的集合。 如果 Set 混入类在具有不同构造器签名的类中被使用,你将需要通过一个能根据可迭代对象参数构造新实例的类方法或常规方法来重写 _from_iterable()。

  2. 要重写比较运算(应该是为了提高速度,因为其语义是固定的),请重新定义 __le__() 和 __ge__(),然后其他运算将自动跟进。

  3. Set 混入类提供了一个 _hash() 方法为集合计算哈希值;但是,__hash__() 没有被定义因为并非所有集合都是 hashable 或不可变对象。 要使用混入类为集合添加可哈希性,请同时继承 Set() 和 Hashable(),然后定义 __hash__ = Set._hash。

参见