collections.abc
--- 容器的抽象基類(lèi)?
3.3 新版功能: 該模塊曾是 collections
模塊的組成部分。
該模塊定義了一些 抽象基類(lèi),它們可用于判斷一個(gè)具體類(lèi)是否具有某一特定的接口;例如,這個(gè)類(lèi)是否可哈希,或其是否為映射類(lèi)。
An issubclass()
or isinstance()
test for an interface works in one
of three ways.
1) A newly written class can inherit directly from one of the abstract base classes. The class must supply the required abstract methods. The remaining mixin methods come from inheritance and can be overridden if desired. Other methods may be added as needed:
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) Existing classes and built-in classes can be registered as "virtual
subclasses" of the ABCs. Those classes should define the full API
including all of the abstract methods and all of the mixin methods.
This lets users rely on issubclass()
or isinstance()
tests
to determine whether the full interface is supported. The exception to
this rule is for methods that are automatically inferred from the rest
of the 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
In this example, class D
does not need to define
__contains__
, __iter__
, and __reversed__
because the
in-operator, the iteration
logic, and the reversed()
function automatically fall back to
using __getitem__
and __len__
.
3) Some simple interfaces are directly recognizable by the presence of
the required methods (unless those methods have been set to
None
):
class E:
def __iter__(self): ...
def __next__(next): ...
>>> issubclass(E, Iterable)
True
>>> isinstance(E(), Iterable)
True
Complex interfaces do not support this last technique because an
interface is more than just the presence of method names. Interfaces
specify semantics and relationships between methods that cannot be
inferred solely from the presence of specific method names. For
example, knowing that a class supplies __getitem__
, __len__
, and
__iter__
is insufficient for distinguishing a Sequence
from
a Mapping
.
3.9 新版功能: These abstract classes now support []
. See GenericAlias 類(lèi)型
and PEP 585.
容器抽象基類(lèi)?
這個(gè)容器模塊提供了以下 ABCs:
抽象基類(lèi) |
繼承自 |
抽象方法 |
Mixin 方法 |
---|---|---|---|
|
|||
|
|||
|
|||
|
|
||
|
|||
|
|
||
|
|||
|
|||
|
|||
|
|
||
|
繼承自 |
||
|
繼承自 |
||
|
|
||
|
繼承自 |
||
|
|
||
|
繼承自 |
||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|
||
|
|||
|
|
||
|
|
Footnotes
- 1(1,2,3,4,5,6,7,8,9,10,11,12,13,14)
These ABCs override
object.__subclasshook__()
to support testing an interface by verifying the required methods are present and have not been set toNone
. This only works for simple interfaces. More complex interfaces require registration or direct subclassing.- 2
Checking
isinstance(obj, Iterable)
detects classes that are registered asIterable
or that have an__iter__()
method, but it does not detect classes that iterate with the__getitem__()
method. The only reliable way to determine whether an object is iterable is to calliter(obj)
.
Collections Abstract Base Classes -- Detailed Descriptions?
- class collections.abc.Container?
提供了
__contains__()
方法的抽象基類(lèi)。
- class collections.abc.Hashable?
提供了
__hash__()
方法的抽象基類(lèi)。
- class collections.abc.Sized?
提供了
__len__()
方法的抽象基類(lèi)。
- class collections.abc.Callable?
提供了
__call__()
方法的抽象基類(lèi)。
- class collections.abc.Iterable?
提供了
__iter__()
方法的抽象基類(lèi)。使用
isinstance(obj, Iterable)
可以檢測(cè)一個(gè)類(lèi)是否已經(jīng)注冊(cè)到了Iterable
或者實(shí)現(xiàn)了__iter__()
函數(shù),但是無(wú)法檢測(cè)這個(gè)類(lèi)是否能夠使用__getitem__()
方法進(jìn)行迭代。檢測(cè)一個(gè)對(duì)象是否是 iterable 的唯一可信賴(lài)的方法是調(diào)用iter(obj)
。
- class collections.abc.Collection?
集合了 Sized 和 Iterable 類(lèi)的抽象基類(lèi)。
3.6 新版功能.
- class collections.abc.Iterator?
提供了
__iter__()
和__next__()
方法的抽象基類(lèi)。參見(jiàn) iterator 的定義。
- class collections.abc.Reversible?
為可迭代類(lèi)提供了
__reversed__()
方法的抽象基類(lèi)。3.6 新版功能.
- class collections.abc.Generator?
生成器類(lèi),實(shí)現(xiàn)了 PEP 342 中定義的協(xié)議,繼承并擴(kuò)展了迭代器,提供了
send()
,throw()
和close()
方法。參見(jiàn) generator 的定義。3.5 新版功能.
- class collections.abc.Sequence?
- class collections.abc.MutableSequence?
- class collections.abc.ByteString?
只讀且可變的序列 sequences 的抽象基類(lèi)。
實(shí)現(xiàn)筆記:一些混入(Maxin)方法比如
__iter__()
,__reversed__()
和index()
會(huì)重復(fù)調(diào)用底層的__getitem__()
方法。因此,如果實(shí)現(xiàn)的__getitem__()
是常數(shù)級(jí)訪問(wèn)速度,那么相應(yīng)的混入方法會(huì)有一個(gè)線性的表現(xiàn);然而,如果底層方法是線性實(shí)現(xiàn)(例如鏈表),那么混入方法將會(huì)是平方級(jí)的表現(xiàn),這也許就需要被重構(gòu)了。在 3.5 版更改: index() 方法支持 stop 和 start 參數(shù)。
- class collections.abc.MappingView?
- class collections.abc.ItemsView?
- class collections.abc.KeysView?
- class collections.abc.ValuesView?
映射及其鍵和值的視圖 views 的抽象基類(lèi)。
- class collections.abc.Awaitable?
為可等待對(duì)象 awaitable 提供的類(lèi),可以被用于
await
表達(dá)式中。習(xí)慣上必須實(shí)現(xiàn)__await__()
方法。協(xié)程 對(duì)象和
Coroutine
ABC 的實(shí)例都是這個(gè) ABC 的實(shí)例。備注
In CPython, generator-based coroutines (generators decorated with
types.coroutine()
) are awaitables, even though they do not have an__await__()
method. Usingisinstance(gencoro, Awaitable)
for them will returnFalse
. Useinspect.isawaitable()
to detect them.3.5 新版功能.
- class collections.abc.Coroutine?
用于協(xié)程兼容類(lèi)的抽象基類(lèi)。實(shí)現(xiàn)了如下定義在 協(xié)程對(duì)象: 里的方法:
send()
,throw()
和close()
。通常的實(shí)現(xiàn)里還需要實(shí)現(xiàn)__await__()
方法。所有的Coroutine
實(shí)例都必須是Awaitable
實(shí)例。參見(jiàn) coroutine 的定義。備注
In CPython, generator-based coroutines (generators decorated with
types.coroutine()
) are awaitables, even though they do not have an__await__()
method. Usingisinstance(gencoro, Coroutine)
for them will returnFalse
. Useinspect.isawaitable()
to detect them.3.5 新版功能.
- class collections.abc.AsyncIterable?
提供了
__aiter__
方法的抽象基類(lèi)。參見(jiàn) asynchronous iterable 的定義。3.5 新版功能.
- class collections.abc.AsyncIterator?
提供了
__aiter__
和__anext__
方法的抽象基類(lèi)。參見(jiàn) asynchronous iterator 的定義。3.5 新版功能.
Examples and Recipes?
ABCs allow us to ask classes or instances if they provide particular functionality, for example:
size = None
if isinstance(myvar, collections.abc.Sized):
size = len(myvar)
有些抽象基類(lèi)也可以用作混入類(lèi)(mixin),這可以更容易地開(kāi)發(fā)支持容器 API 的類(lèi)。例如,要寫(xiě)一個(gè)支持完整 Set
API 的類(lèi),只需要提供下面這三個(gè)方法: __contains__()
, __iter__()
和 __len__()
。抽象基類(lèi)會(huì)補(bǔ)充上其余的方法,比如 __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
當(dāng)把 Set
和 MutableSet
用作混入類(lèi)時(shí)需注意:
由于某些集合操作會(huì)創(chuàng)建新集合,默認(rèn)的混入方法需要一種從可迭代對(duì)象里創(chuàng)建新實(shí)例的方式。 假定類(lèi)構(gòu)造器具有
ClassName(iterable)
形式的簽名。 這樣它將執(zhí)行一個(gè)名為_from_iterable()
的內(nèi)部類(lèi)方法,該方法會(huì)調(diào)用cls(iterable)
來(lái)產(chǎn)生一個(gè)新集合。 如果Set
混入類(lèi)在具有不同構(gòu)造器簽名的類(lèi)中被使用,你將需要通過(guò)類(lèi)方法或常規(guī)方法來(lái)重載_from_iterable()
,以便基于可迭代對(duì)象參數(shù)來(lái)構(gòu)造新的實(shí)例。重載比較符時(shí)時(shí)(想必是為了速度,因?yàn)槠湔Z(yǔ)義都是固定的),只需要重定義
__le__()
和__ge__()
函數(shù),然后其他的操作會(huì)自動(dòng)跟進(jìn)。混入集合類(lèi)
Set
提供了一個(gè)_hash()
方法為集合計(jì)算哈希值,然而,__hash__()
函數(shù)卻沒(méi)有被定義,因?yàn)椴⒉皇撬屑隙际强晒2⑶也豢勺兊?。為了使用混入?lèi)為集合添加哈希能力,可以同時(shí)繼承Set()
和Hashable()
類(lèi),然后定義__hash__ = Set._hash
。
參見(jiàn)
OrderedSet recipe 是基于
MutableSet
構(gòu)建的一個(gè)示例。