collections.abc — 容器的抽象基类 — Python 文档

来自菜鸟教程
Python/docs/3.10/library/collections.abc
跳转至:导航、​搜索

collections.abc — 容器的抽象基类

3.3 新功能: 以前,这个模块是 collections 模块的一部分。


源代码: :source:`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,包括所有抽象方法和所有 mixin 方法。 这让用户可以依靠 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__,因为 在运算符 中, 迭代逻辑,reversed()函数自动回退到使用__getitem____len__

3)一些简单的接口可以通过所需方法的存在直接识别(除非这些方法已设置为None):

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

复杂接口不支持最后一种技术,因为接口不仅仅是方法名称的存在。 接口指定不能仅从特定方法名称的存在推断的方法之间的语义和关系。 例如,知道一个类提供 __getitem____len____iter__ 不足以区分 SequenceMapping .

3.9 新功能:这些抽象类现在支持[]。 请参阅 通用别名类型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 sendthrow close__iter____next__
Sized 1 __len__
Callable 1 __call__
Collection 1 大小可迭代容器 __contains____iter____len__
Sequence 可逆收藏 __getitem____len__ __contains____iter____reversed__indexcount
MutableSequence Sequence __getitem____setitem____delitem____len__insert 继承了 Sequence 方法和 appendreverseextendpopremove 和 [ X103X]
ByteString Sequence __getitem____len__ 继承 序列 方法
Set Collection __contains____iter____len__ __le____lt____eq____ne____gt____ge____and__、[ X77X]、__sub____xor__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 __len__
ItemsView MappingView, Set __contains____iter__
KeysView MappingView, Set __contains____iter__
ValuesView 映射视图集合 __contains____iter__
Awaitable 1 __await__
Coroutine 1 Awaitable sendthrow close
AsyncIterable 1 __aiter__
AsyncIterator 1 AsyncIterable __anext__ __aiter__
AsyncGenerator 1 AsyncIterator asendathrow aclose__aiter____anext__

脚注

1(1,2,3,4,5,6,[ X67X]7,8,9,10,11,12, 13,14)
这些 ABC 覆盖 object.__subclasshook__() 以通过验证所需的方法是否存在并且尚未设置为 None 来支持测试接口。 这仅适用于简单的接口。 更复杂的接口需要注册或直接子类化。
2
检查 isinstance(obj, Iterable) 会检测注册为 Iterable 或具有 __iter__() 方法的类,但不会检测使用 __getitem__() 方法迭代的类。 确定对象是否为 iterable 的唯一可靠方法是调用 iter(obj)


集合抽象基类——详细描述

class collections.abc.Container
提供 __contains__() 方法的类的 ABC。
class collections.abc.Hashable
提供 __hash__() 方法的类的 ABC。
class collections.abc.Sized
提供 __len__() 方法的类的 ABC。
class collections.abc.Callable
提供 __call__() 方法的类的 ABC。
class collections.abc.Iterable

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

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

class collections.abc.Collection

用于大小可迭代容器类的 ABC。

3.6 版中的新功能。

class collections.abc.Iterator
ABC 用于提供 __iter__()__next__() 方法的类。 另见迭代器的定义。
class collections.abc.Reversible

ABC 用于还提供 __reversed__() 方法的可迭代类。

3.6 版中的新功能。

class collections.abc.Generator

用于实现 PEP 342 中定义的协议的生成器类的 ABC,它使用 send()throw() 和 扩展迭代器X161X]close() 方法。 另见发电机的定义。

3.5 版中的新功能。

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

用于只读和可变 序列 的 ABC。

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

3.5 版更改: index() 方法添加了对 stopstart 参数的支持。

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

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

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

笔记

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

3.5 版中的新功能。

class collections.abc.Coroutine

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

笔记

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

3.5 版中的新功能。

class collections.abc.AsyncIterable

提供 __aiter__ 方法的类的 ABC。 另见异步可迭代的定义。

3.5 版中的新功能。

class collections.abc.AsyncIterator

ABC 用于提供 __aiter____anext__ 方法的类。 另见异步迭代器的定义。

3.5 版中的新功能。

class collections.abc.AsyncGenerator

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

3.6 版中的新功能。


例子和食谱

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

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

一些 ABC 也可用作 mixin,可以更轻松地开发支持容器 API 的类。 例如,要编写一个支持完整的 Set API 的类,只需要提供三个底层抽象方法:__contains__()__iter__() 和 [ X168X]。 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 作为 mixin 的注意事项:

  1. 由于某些集合操作会创建新集合,因此默认的 mixin 方法需要一种从可迭代对象创建新实例的方法。 假定类构造函数具有 ClassName(iterable) 形式的签名。 该假设被分解为称为 _from_iterable() 的内部类方法,该方法调用 cls(iterable) 以生成新集合。 如果在具有不同构造函数签名的类中使用 Set 混合函数,则需要使用类方法或常规方法覆盖 _from_iterable(),该方法可以从可迭代参数构造新实例。
  2. 要覆盖比较(大概是为了速度,因为语义是固定的),重新定义 __le__()__ge__(),然后其他操作将自动效仿。
  3. Set mixin 提供了一个 _hash() 方法来计算集合的哈希值; 然而,__hash__() 并未定义,因为并非所有集合都是可散列或不可变的。 要使用 mixin 添加 set hashability,请继承 Set()Hashable(),然后定义 __hash__ = Set._hash

也可以看看