collections.abc
--- 容器的抽象基类¶
Added in version 3.3: 该模块曾是 collections
模块的组成部分。
本模块提供了一些 抽象基类,它们可被用于测试一个类是否提供某个特定的接口;例如,它是否为 hashable 或是否为 mapping 等。
一个接口的 issubclass()
或 isinstance()
测试采用以下三种方式之一。
新编写的类可以直接继承自某个抽象基类。 该类必须提供所面的抽象方法。 其他混入方法来自于继承并且可在需要时被重写。 其他方法可以被按需添加:
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
已有的类和内置类可被注册为 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__
。某些简单接口可以根据所需方法是否存在来直接识别 (除非这些方法已被设置为
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。
容器抽象基类¶
这个容器模块提供了以下 ABCs:
抽象基类 |
继承自 |
抽象方法 |
Mixin 方法 |
---|---|---|---|
|
|||
|
|||
|
|||
|
|
||
|
|||
|
|
||
|
|||
|
|||
|
|||
|
|
||
|
继承了 |
||
|
|
||
|
继承自 |
||
|
|
||
|
继承自 |
||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|
||
|
|||
|
|
||
|
|
||
|
附注
多项集抽象基类 -- 详细描述¶
- class collections.abc.Container¶
提供了
__contains__()
方法的抽象基类。
- class collections.abc.Hashable¶
提供了
__hash__()
方法的抽象基类。
- 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¶
集合了 Sized 和 Iterable 类的抽象基类。
Added in version 3.6.
- class collections.abc.Iterator¶
提供了
__iter__()
和__next__()
方法的抽象基类。参见 iterator 的定义。
- class collections.abc.Reversible¶
用于同时提供了
__reversed__()
方法的可迭代类的 ABCAdded 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¶
只读的与可变的 序列 的抽象基类。
实现注意事项:某些混入方法,如
__iter__()
,__reversed__()
和index()
,会重复调用下层的__getitem__()
方法。 因此,如果__getitem__()
被实现为常数级访问速度,则混入方法的性能将为线性级;但是,如果下层的方法是线性的(例如链表就是如此),则混入方法的性能将为平方级并可能需要被重写。在 3.5 版本发生变更: index() 方法支持 stop 和 start 参数。
- 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
用作混入类时需注意:
由于某些集合操作会创建新的集合,默认的混入方法需要一种根据 iterable 创建新实例的方式。 类构造器应当具有
ClassName(iterable)
形式的签名。 这样它将被重构为一个执行_from_iterable()
的内部classmethod
,该方法会调用cls(iterable)
来产生一个新的集合。 如果Set
混入类在具有不同构造器签名的类中被使用,你将需要通过一个能根据可迭代对象参数构造新实例的类方法或常规方法来重写_from_iterable()
。要重写比较运算(应该是为了提高速度,因为其语义是固定的),请重新定义
__le__()
和__ge__()
,然后其他运算将自动跟进。Set
混入类提供了一个_hash()
方法为集合计算哈希值;但是,__hash__()
没有被定义因为并非所有集合都是 hashable 或不可变对象。 要使用混入类为集合添加可哈希性,请同时继承Set()
和Hashable()
,然后定义__hash__ = Set._hash
。
参见
OrderedSet recipe 是基于
MutableSet
构建的一个示例。