collections.abc
--- 容器的抽象基类¶
在 3.3 版本加入: 以前,此模块是 collections
模块的一部分。
此模块提供了抽象基类,可用于测试某个类是否提供了特定的接口;例如,它是否是 可哈希的 或它是否是 映射。
对某个接口的 issubclass()
或 isinstance()
测试有三种工作方式。
新编写的类可以直接从某个抽象基类继承。该类必须提供所需的抽象方法。其余的混入(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
现有类和内置类可以注册为 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__
。一些简单的接口可以通过所需方法的出现来直接识别(除非这些方法被设置为
None
)。class E: def __iter__(self): ... def __next__(self): ...
>>> issubclass(E, Iterable) True >>> isinstance(E(), Iterable) True
复杂的接口不支持最后这种技术,因为一个接口不仅仅是方法名的存在。接口指定了方法之间的语义和关系,这些是无法仅通过特定方法名的存在来推断的。例如,知道一个类提供了
__getitem__
、__len__
和__iter__
不足以区分Sequence
和Mapping
。
容器的抽象基类¶
collections 模块提供了以下 ABC:
ABC |
继承自 |
抽象方法 |
混入方法 |
---|---|---|---|
|
|||
|
|||
|
|||
|
|
||
|
|||
|
|
||
|
|||
|
|||
|
|||
|
|
||
|
继承的 |
||
|
继承的 |
||
|
|
||
|
继承的 |
||
|
|
||
|
继承的 |
||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|
||
|
|||
|
|
||
|
|
||
|
脚注
容器抽象基类 – 详细描述¶
- class collections.abc.Container¶
为提供了
__contains__()
方法的类提供的 ABC。
- class collections.abc.Hashable¶
为提供了
__hash__()
方法的类提供的 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
。支持 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.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.AsyncIterator¶
为提供了
__aiter__
和__anext__
方法的类提供的 ABC。另请参见 异步迭代器 的定义。在 3.5 版本加入。
- class collections.abc.AsyncGenerator¶
为异步生成器类提供的 ABC,它实现了 PEP 525 和 PEP 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
关于将 Set
和 MutableSet
用作混入的说明:
由于某些集合操作会创建新的集合,因此默认的混入方法需要一种方法来从可迭代对象创建新实例。类的构造函数被假定为具有
ClassName(iterable)
形式的签名。这个假设被分解为一个名为_from_iterable()
的内部classmethod
,它调用cls(iterable)
来产生一个新的集合。如果在具有不同构造函数签名的类中使用Set
混入,你需要用一个类方法或常规方法来重写_from_iterable()
,该方法可以从一个可迭代参数构造新实例。要重写比较(可能是为了速度,因为语义是固定的),请重新定义
__le__()
和__ge__()
,然后其他操作将自动跟进。Set
混入提供了一个_hash()
方法来计算集合的哈希值;但是,__hash__()
没有被定义,因为并非所有集合都是可哈希的或不可变的。要使用混入添加集合的可哈希性,请同时从Set()
和Hashable()
继承,然后定义__hash__ = Set._hash
。
参见
OrderedSet 配方 是一个基于
MutableSet
构建的示例。