collections.abc — 容器的抽象基类 — Python 文档
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__
不足以区分 Sequence 和 Mapping .
集合抽象基类
collections 模块提供以下 ABCs:
美国广播公司 | 继承自 | 抽象方法 | 混合方法 |
---|---|---|---|
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
|
大小,可迭代,容器 | __contains__ 、__iter__ 、__len__
|
|
Sequence
|
可逆,收藏 | __getitem__ 、__len__
|
__contains__ 、__iter__ 、__reversed__ 、index 和 count
|
MutableSequence
|
Sequence
|
__getitem__ 、__setitem__ 、__delitem__ 、__len__ 、insert
|
继承了 Sequence 方法和 append 、reverse 、extend 、pop 、remove 和 [ 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__ 、add 、discard
|
继承了 Set 方法和 clear 、pop 、remove 、__ior__ 、__iand__ 、__ixor__ ] 和 __isub__
|
Mapping
|
Collection
|
__getitem__ 、__iter__ 、__len__
|
__contains__ 、keys 、items 、values 、get 、__eq__ 和__ne__
|
MutableMapping
|
Mapping
|
__getitem__ 、__setitem__ 、__delitem__ 、__iter__ 、__len__
|
继承了 Mapping 方法和 pop 、popitem 、clear 、update 和 setdefault
|
MappingView
|
Sized
|
__len__
| |
ItemsView
|
MappingView, Set | __contains__ 、__iter__
| |
KeysView
|
MappingView, Set | __contains__ 、__iter__
| |
ValuesView
|
映射视图、集合 | __contains__ 、__iter__
| |
Awaitable 1
|
__await__
|
||
Coroutine 1
|
Awaitable
|
send 、throw
|
close
|
AsyncIterable 1
|
__aiter__
|
||
AsyncIterator 1
|
AsyncIterable
|
__anext__
|
__aiter__
|
AsyncGenerator 1
|
AsyncIterator
|
asend 、athrow
|
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() 方法添加了对 stop 和 start 参数的支持。
- 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 版中的新功能。
例子和食谱
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
使用 Set 和 MutableSet 作为 mixin 的注意事项:
- 由于某些集合操作会创建新集合,因此默认的 mixin 方法需要一种从可迭代对象创建新实例的方法。 假定类构造函数具有
ClassName(iterable)
形式的签名。 该假设被分解为称为_from_iterable()
的内部类方法,该方法调用cls(iterable)
以生成新集合。 如果在具有不同构造函数签名的类中使用 Set 混合函数,则需要使用类方法或常规方法覆盖_from_iterable()
,该方法可以从可迭代参数构造新实例。 - 要覆盖比较(大概是为了速度,因为语义是固定的),重新定义
__le__()
和__ge__()
,然后其他操作将自动效仿。 - Set mixin 提供了一个
_hash()
方法来计算集合的哈希值; 然而,__hash__()
并未定义,因为并非所有集合都是可散列或不可变的。 要使用 mixin 添加 set hashability,请继承 Set() 和 Hashable(),然后定义__hash__ = Set._hash
。