collections.abc --- 容器的抽象基類

在 3.3 版本加入: 以前,此模組是 collections 模組的一部分。

原始碼: 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,包括所有的抽象方法和所有的混入方法。這讓使用者可以依賴 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__ 不足以區分 SequenceMapping

在 3.9 版本加入: 這些抽象類現在支援 []。參見 泛型別名型別PEP 585

容器的抽象基類

collections 模組提供了以下 ABC

ABC

繼承自

抽象方法

混入方法

Container [1]

__contains__

Hashable [1]

__hash__

Iterable [1] [2]

__iter__

Iterator [1]

Iterable

__next__

__iter__

Reversible [1]

Iterable

__reversed__

Generator [1]

Iterator

sendthrow

close, __iter__, __next__

Sized [1]

__len__

Callable [1]

__call__

Collection [1]

SizedIterableContainer

__contains____iter____len__

Sequence

Reversible, Collection

__getitem__, __len__

__contains____iter____reversed__indexcount

MutableSequence

Sequence

__getitem____setitem____delitem____len__insert

繼承的 Sequence 方法和 appendclearreverseextendpopremove__iadd__

ByteString

Sequence

__getitem__, __len__

繼承的 Sequence 方法

Set

Collection

__contains____iter____len__

__le____lt____eq____ne____gt____ge____and____or____sub____rsub____xor____rxor__isdisjoint

MutableSet

Set

__contains____iter____len__adddiscard

繼承的 Set 方法和 clearpopremove__ior____iand____ixor____isub__

Mapping

Collection

__getitem____iter____len__

__contains__keysitemsvaluesget__eq____ne__

MutableMapping

Mapping

__getitem____setitem____delitem____iter____len__

繼承的 Mapping 方法和 poppopitemclearupdatesetdefault

MappingView

Sized

__init__, __len__ and __repr__

ItemsView

MappingView, Set

__contains__, __iter__

KeysView

MappingView, Set

__contains__, __iter__

ValuesView

MappingView, Collection

__contains__, __iter__

Awaitable [1]

__await__

Coroutine [1]

Awaitable

sendthrow

close

AsyncIterable [1]

__aiter__

AsyncIterator [1]

AsyncIterable

__anext__

__aiter__

AsyncGenerator [1]

AsyncIterator

asend, athrow

aclose__aiter____anext__

Buffer [1]

__buffer__

腳註

容器抽象基類 – 詳細描述

class collections.abc.Container

為提供了 __contains__() 方法的類提供的 ABC。

class collections.abc.Hashable

為提供了 __hash__() 方法的類提供的 ABC。

class collections.abc.Sized

為提供了 __len__() 方法的類提供的 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

支援 startstop 引數是可選的,但推薦使用。

在 3.5 版本發生變更: index() 方法增加了對 stopstart 引數的支援。

自 3.12 版本起棄用,將在 3.17 版本中刪除: ByteString ABC 已被棄用。

使用 isinstance(obj, collections.abc.Buffer) 來在執行時測試 obj 是否實現了緩衝區協議。在型別註解中,請使用 Buffer 或明確指定程式碼所支援的型別的聯合型別(例如,bytes | bytearray | memoryview)。

ByteString 最初旨在作為一個抽象類,同時作為 bytesbytearray 的超型別。然而,由於這個 ABC 從未有過任何方法,所以知道一個物件是 ByteString 的例項實際上並不能告訴你任何關於該物件的有用資訊。其他常見的緩衝區型別,如 memoryview,也從未被理解為 ByteString 的子型別(無論是在執行時還是透過靜態型別檢查器)。

更多細節請參閱 PEP 688

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

可等待物件 提供的 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.AsyncIterable

為提供了 __aiter__ 方法的類提供的 ABC。另請參見 非同步可迭代物件 的定義。

在 3.5 版本加入。

class collections.abc.AsyncIterator

為提供了 __aiter____anext__ 方法的類提供的 ABC。另請參見 非同步迭代器 的定義。

在 3.5 版本加入。

class collections.abc.AsyncGenerator

非同步生成器類提供的 ABC,它實現了 PEP 525PEP 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

關於將 SetMutableSet 用作混入的說明:

  1. 由於某些集合操作會建立新的集合,因此預設的混入方法需要一種方法來從可迭代物件建立新例項。類的建構函式被假定為具有 ClassName(iterable) 形式的簽名。這個假設被分解為一個名為 _from_iterable() 的內部 classmethod,它呼叫 cls(iterable) 來產生一個新的集合。如果在具有不同建構函式簽名的類中使用 Set 混入,你需要用一個類方法或常規方法來重寫 _from_iterable(),該方法可以從一個可迭代引數構造新例項。

  2. 要重寫比較(可能是為了速度,因為語義是固定的),請重新定義 __le__()__ge__(),然後其他操作將自動跟進。

  3. Set 混入提供了一個 _hash() 方法來計算集合的雜湊值;但是,__hash__() 沒有被定義,因為並非所有集合都是可雜湊的或不可變的。要使用混入新增集合的可雜湊性,請同時從 Set()Hashable() 繼承,然後定義 __hash__ = Set._hash

參見