collections.abc — 容器的抽象基类

3.3 版新增: 此模块之前是 collections 模块的一部分。

源代码: Lib/_collections_abc.py


此模块提供了 抽象基类,可用于测试类是否提供了特定的接口;例如,它是否 可哈希 或它是否是 映射

对接口进行 issubclass()isinstance() 测试可以通过以下三种方式之一进行。

1) 新编写的类可以直接从其中一个抽象基类继承。该类必须提供所需的抽象方法。其余的混合方法来自继承,如果需要,可以重写。可以根据需要添加其他方法

class C(Sequence):                      # Direct inheritance
    def __init__(self): ...             # Extra method not required by the ABC
    def __getitem__(self, index):  ...  # Required abstract method
    def __len__(self):  ...             # Required abstract method
    def count(self, value): ...         # Optionally override a mixin method
>>> issubclass(C, Sequence)
True
>>> isinstance(C(), Sequence)
True

2) 现有类和内置类可以注册为 ABC 的“虚拟子类”。这些类应定义完整的 API,包括所有抽象方法和所有混合方法。这允许用户依赖 issubclass()isinstance() 测试来确定是否支持完整的接口。此规则的例外情况是针对从 API 的其余部分自动推断出的方法

class D:                                 # No inheritance
    def __init__(self): ...              # Extra method not required by the ABC
    def __getitem__(self, index):  ...   # Abstract method
    def __len__(self):  ...              # Abstract method
    def count(self, value): ...          # Mixin method
    def index(self, value): ...          # Mixin method

Sequence.register(D)                     # Register instead of inherit
>>> 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__ 不足以区分 SequenceMapping

3.9 版新增: 这些抽象类现在支持 []。请参阅 泛型别名类型PEP 585

集合抽象基类

collections 模块提供了以下 ABC

ABC

继承自

抽象方法

混合方法

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

可变序列

Sequence

__getitem__, __setitem__, __delitem__, __len__, insert

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

字节串

Sequence

__getitem__, __len__

继承自 Sequence 的方法

集合

集合类型

__contains__, __iter__, __len__

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

可变集合

集合

__contains__, __iter__, __len__, add, discard

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

映射

集合类型

__getitem__, __iter__, __len__

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

可变映射

映射

__getitem__, __setitem__, __delitem__, __iter__, __len__

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

映射视图

可估量大小

__len__

键值对视图

MappingView, Set

__contains__, __iter__

键视图

MappingView, Set

__contains__, __iter__

值视图

MappingView, Collection

__contains__, __iter__

Awaitable [1]

__await__

Coroutine [1]

可等待对象

send, throw

close

AsyncIterable [1]

__aiter__

AsyncIterator [1]

异步可迭代对象

__anext__

__aiter__

AsyncGenerator [1]

异步迭代器

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。

class collections.abc.Iterable

针对提供 __iter__() 方法的类的 ABC。

检查 isinstance(obj, Iterable) 可以检测注册为 Iterable 的类或具有 __iter__() 方法的类,但它无法检测使用 __getitem__() 方法进行迭代的类。确定对象是否为 可迭代 的唯一可靠方法是调用 iter(obj)

class collections.abc.Collection

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

3.6 版新增。

class collections.abc.Iterator

针对提供 __iter__()__next__() 方法的类的 ABC。另请参阅 迭代器 的定义。

class collections.abc.Reversible

针对也提供 __reversed__() 方法的可迭代类的 ABC。

3.6 版新增。

class collections.abc.Generator

针对实现 PEP 342 中定义的协议的 生成器 类的 ABC,该协议使用 send()throw()close() 方法扩展了 迭代器

3.5 版新增。

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

针对只读和可变 序列 的 ABC。

实现说明:某些混入方法,例如 __iter__()__reversed__()index(),会重复调用底层的 __getitem__() 方法。因此,如果 __getitem__() 是以恒定访问速度实现的,则混入方法将具有线性性能;但是,如果底层方法是线性的(就像链表那样),则混入方法将具有二次性能,并且可能需要被覆盖。

在 3.5 版更改: index() 方法添加了对 *stop* 和 *start* 参数的支持。

自 3.12 版弃用,将在 3.14 版移除: ByteString ABC 已被弃用。如果用于类型提示,建议使用联合类型,例如 bytes | bytearraycollections.abc.Buffer。如果用作 ABC,建议使用 Sequencecollections.abc.Buffer

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

针对只读和可变 集合 的 ABC。

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

针对只读和可变 映射 的 ABC。

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

针对映射、项、键和值 视图 的 ABC。

class collections.abc.Awaitable

针对 可等待 对象的 ABC,可以在 await 表达式中使用。自定义实现必须提供 __await__() 方法。

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

注意

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

3.5 版新增。

class collections.abc.Coroutine

协程 兼容的类的 ABC。它们实现了以下方法,这些方法在 协程对象 中定义:send()throw()close()。自定义实现还必须实现 __await__()。所有 Coroutine 实例也是 Awaitable 的实例。

注意

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

3.5 版新增。

class collections.abc.AsyncIterable

提供 __aiter__ 方法的类的 ABC。另请参阅 异步可迭代对象 的定义。

3.5 版新增。

class collections.abc.AsyncIterator

提供 __aiter____anext__ 方法的类的 ABC。另请参阅 异步迭代器 的定义。

3.5 版新增。

class collections.abc.AsyncGenerator

实现了 PEP 525PEP 492 中定义的协议的 异步生成器 类的 ABC。

3.6 版新增。

class collections.abc.Buffer

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

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):
    ''' Alternate set implementation favoring space over speed
        and not requiring the set elements to be hashable. '''
    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            # The __and__() method is supported automatically

关于使用 SetMutableSet 作为混入类的注意事项

  1. 由于某些集合操作会创建新的集合,因此默认的混入方法需要一种从 可迭代对象 创建新实例的方法。假定类构造函数的签名形式为 ClassName(iterable)。该假设被分解为一个名为 _from_iterable() 的内部 classmethod,它调用 cls(iterable) 来生成一个新的集合。如果在具有不同构造函数签名的类中使用 Set 混入类,则需要使用可以从可迭代参数构造新实例的类方法或常规方法覆盖 _from_iterable()

  2. 要覆盖比较(可能是为了速度,因为语义是固定的),请重新定义 __le__()__ge__(),然后其他操作将自动随之进行。

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

另请参阅