collections.abc
— 容器的抽象基類¶
3.3 版本新增: 此模組以前是 collections
模組的一部分。
此模組提供了抽象基類,可用於測試一個類是否提供了特定的介面;例如,它是否可雜湊或是否是對映。
對介面的 issubclass()
或 isinstance()
測試以三種方式之一工作。
1) 新編寫的類可以直接從其中一個抽象基類繼承。該類必須提供所需的抽象方法。其餘的混合方法來自繼承,並且可以根據需要進行重寫。其他方法可以根據需要新增
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__
不足以區分 Sequence
和 Mapping
。
集合抽象基類¶
集合模組提供以下ABCs
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¶
為實現 PEP 342 中定義的協議的 生成器 類提供的 ABC,該協議使用
send()
,throw()
和close()
方法擴充套件了 迭代器。有關在型別註解中使用
Generator
的詳細資訊,請參閱 註解生成器和協程。3.5 版本新增。
- class collections.abc.Sequence¶
- class collections.abc.MutableSequence¶
- class collections.abc.ByteString¶
用於只讀和可變序列的 ABC。
實現說明:一些混入方法,例如
__iter__()
、__reversed__()
和index()
,會重複呼叫底層__getitem__()
方法。因此,如果__getitem__()
的實現具有恆定的訪問速度,則混入方法將具有線性效能;但是,如果底層方法是線性的(就像連結串列一樣),則混入方法將具有二次效能,並且可能需要被覆蓋。在 3.5 版本中變更: index() 方法增加了對 stop 和 start 引數的支援。
自 3.12 版本起棄用,將在 3.14 版本中移除:
ByteString
ABC 已被棄用。在型別標註中使用時,請優先使用聯合型別,例如bytes | bytearray
或collections.abc.Buffer
。作為 ABC 使用時,請優先使用Sequence
或collections.abc.Buffer
。
- 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¶
用於實現 PEP 525 和 PEP 492 中定義的協議的 非同步生成器 類的 ABC。
有關在型別標註中使用
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 也可用作混入類,以便更容易開發支援容器 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)
形式的簽名。該假設被分解為一個內部的classmethod
,稱為_from_iterable()
,它呼叫cls(iterable)
來生成一個新的集合。如果Set
混入類被用於具有不同建構函式簽名的類中,則需要使用一個可以從可迭代引數構造新例項的類方法或常規方法來覆蓋_from_iterable()
。要覆蓋比較(可能是為了提高速度,因為語義是固定的),請重新定義
__le__()
和__ge__()
,然後其他操作將自動跟進。Set
混入類提供了一個_hash()
方法來計算集合的雜湊值;但是,__hash__()
沒有定義,因為並非所有集合都是 可雜湊的 或不可變的。要使用混入類新增集合的可雜湊性,請同時繼承自Set()
和Hashable()
,然後定義__hash__ = Set._hash
。
另請參閱
OrderedSet recipe,這是一個基於
MutableSet
構建的示例。