# `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__` |

附注

[1] (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)

这些 ABC 重写了 `__subclasshook__()` 以便支持通过验证所需的方法是否存在并且没有被设为 `None` 来测试一个接口。 这只适用于简单的接口。 更复杂的接口需要注册或者直接子类化。

[2]

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

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

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`。

参见

- OrderedSet recipe 是基于 `MutableSet` 构建的一个示例。

- 有关 ABC 的更多信息，参见 `abc` 模块和 PEP 3119。