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
構建的示例。