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 版本中刪除:
ByteStringABC 已被棄用。使用
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__()方法。協程 物件和
CoroutineABC 的例項都是此 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構建的示例。