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

在 3.3 版本加入: 以前,此模块是 collections 模块的一部分。

源代码: Lib/_collections_abc.py


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

对某个接口的 issubclass()isinstance() 测试有三种工作方式。

  1. 新编写的类可以直接从某个抽象基类继承。该类必须提供所需的抽象方法。其余的混入(mixin)方法通过继承获得,如果需要也可以被重写。还可以根据需要添加其他方法。

    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

sendthrow

close, __iter__, __next__

Sized [1]

__len__

Callable [1]

__call__

Collection [1]

SizedIterableContainer

__contains____iter____len__

Sequence

Reversible, Collection

__getitem__, __len__

__contains____iter____reversed__indexcount

MutableSequence

Sequence

__getitem____setitem____delitem____len__insert

继承的 Sequence 方法和 appendclearreverseextendpopremove__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__adddiscard

继承的 Set 方法和 clearpopremove__ior____iand____ixor____isub__

Mapping

Collection

__getitem____iter____len__

__contains__keysitemsvaluesget__eq____ne__

MutableMapping

Mapping

__getitem____setitem____delitem____iter____len__

继承的 Mapping 方法和 poppopitemclearupdatesetdefault

MappingView

Sized

__init__, __len__ and __repr__

ItemsView

MappingView, Set

__contains__, __iter__

KeysView

MappingView, Set

__contains__, __iter__

ValuesView

MappingView, Collection

__contains__, __iter__

Awaitable [1]

__await__

Coroutine [1]

Awaitable

sendthrow

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__() 方法的类提供的 ABC。

class collections.abc.Hashable

为提供了 __hash__() 方法的类提供的 ABC。

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__() 方法进行迭代的类。确定一个对象是否为 可迭代对象 的唯一可靠方法是调用 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

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

关于在类型注解中使用 Generator 的细节,请参阅 为生成器和协程添加注解

在 3.5 版本加入。

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

为只读和可变 序列 提供的 ABC。

实现说明:某些混入方法,如 __iter__()__reversed__()index(),会重复调用底层的 __getitem__() 方法。因此,如果 __getitem__() 是以常数访问速度实现的,那么混入方法将具有线性性能;然而,如果底层方法是线性的(例如链表),那么混入方法将具有平方性能,并且可能需要被重写。

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

返回 value 的第一个索引。

如果值不存在,则引发 ValueError

支持 startstop 参数是可选的,但推荐使用。

在 3.5 版本发生变更: index() 方法增加了对 stopstart 参数的支持。

自 3.12 版本起弃用,将在 3.17 版本中删除: ByteString ABC 已被弃用。

使用 isinstance(obj, collections.abc.Buffer) 来在运行时测试 obj 是否实现了缓冲区协议。在类型注解中,请使用 Buffer 或明确指定代码所支持的类型的联合类型(例如,bytes | bytearray | memoryview)。

ByteString 最初旨在作为一个抽象类,同时作为 bytesbytearray 的超类型。然而,由于这个 ABC 从未有过任何方法,所以知道一个对象是 ByteString 的实例实际上并不能告诉你任何关于该对象的有用信息。其他常见的缓冲区类型,如 memoryview,也从未被理解为 ByteString 的子类型(无论是在运行时还是通过静态类型检查器)。

更多细节请参阅 PEP 688

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() 来检测它们。

有关在类型注解中使用 Coroutine 的详细信息,请参阅为生成器和协程添加注解。类型参数的变异性和顺序与 Generator 的相对应。

在 3.5 版本加入。

class collections.abc.AsyncIterable

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

在 3.5 版本加入。

class collections.abc.AsyncIterator

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

在 3.5 版本加入。

class collections.abc.AsyncGenerator

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

关于在类型注解中使用 AsyncGenerator 的细节,请参阅 为生成器和协程添加注解

在 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 也可用作混入(mixin),它们使开发支持容器 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

参见