14
14
15
15
.. testsetup :: *
16
16
17
- from collections import *
17
+ from collections.abc import *
18
18
import itertools
19
19
__name__ = '<doctest>'
20
20
@@ -24,6 +24,86 @@ This module provides :term:`abstract base classes <abstract base class>` that
24
24
can be used to test whether a class provides a particular interface; for
25
25
example, whether it is hashable or whether it is a mapping.
26
26
27
+ An :func: `issubclass ` or :func: `isinstance ` test for an interface works in one
28
+ of three ways.
29
+
30
+ 1) A newly written class can inherit directly from one of the
31
+ abstract base classes. The class must supply the required abstract
32
+ methods. The remaining mixin methods come from inheritance and can be
33
+ overridden if desired. Other methods may be added as needed:
34
+
35
+ .. testcode ::
36
+
37
+ class C(Sequence): # Direct inheritance
38
+ def __init__(self): ... # Extra method not required by the ABC
39
+ def __getitem__(self, index): ... # Required abstract method
40
+ def __len__(self): ... # Required abstract method
41
+ def count(self, value): ... # Optionally override a mixin method
42
+
43
+ .. doctest ::
44
+
45
+ >>> issubclass (C, Sequence)
46
+ True
47
+ >>> isinstance (C(), Sequence)
48
+ True
49
+
50
+ 2) Existing classes and built-in classes can be registered as "virtual
51
+ subclasses" of the ABCs. Those classes should define the full API
52
+ including all of the abstract methods and all of the mixin methods.
53
+ This lets users rely on :func: `issubclass ` or :func: `isinstance ` tests
54
+ to determine whether the full interface is supported. The exception to
55
+ this rule is for methods that are automatically inferred from the rest
56
+ of the API:
57
+
58
+ .. testcode ::
59
+
60
+ class D: # No inheritance
61
+ def __init__(self): ... # Extra method not required by the ABC
62
+ def __getitem__(self, index): ... # Abstract method
63
+ def __len__(self): ... # Abstract method
64
+ def count(self, value): ... # Mixin method
65
+ def index(self, value): ... # Mixin method
66
+
67
+ Sequence.register(D) # Register instead of inherit
68
+
69
+ .. doctest ::
70
+
71
+ >>> issubclass (D, Sequence)
72
+ True
73
+ >>> isinstance (D(), Sequence)
74
+ True
75
+
76
+ In this example, class :class: `D ` does not need to define
77
+ ``__contains__ ``, ``__iter__ ``, and ``__reversed__ `` because the
78
+ :ref: `in-operator <comparisons >`, the :term: `iteration <iterable> `
79
+ logic, and the :func: `reversed ` function automatically fall back to
80
+ using ``__getitem__ `` and ``__len__ ``.
81
+
82
+ 3) Some simple interfaces are directly recognizable by the presence of
83
+ the required methods (unless those methods have been set to
84
+ :const: `None `):
85
+
86
+ .. testcode ::
87
+
88
+ class E:
89
+ def __iter__(self): ...
90
+ def __next__(next): ...
91
+
92
+ .. doctest ::
93
+
94
+ >>> issubclass (E, Iterable)
95
+ True
96
+ >>> isinstance (E(), Iterable)
97
+ True
98
+
99
+ Complex interfaces do not support this last technique because an
100
+ interface is more than just the presence of method names. Interfaces
101
+ specify semantics and relationships between methods that cannot be
102
+ inferred solely from the presence of specific method names. For
103
+ example, knowing that a class supplies ``__getitem__ ``, ``__len__ ``, and
104
+ ``__iter__ `` is insufficient for distinguishing a :class: `Sequence ` from
105
+ a :class: `Mapping `.
106
+
27
107
28
108
.. _collections-abstract-base-classes :
29
109
@@ -34,67 +114,86 @@ The collections module offers the following :term:`ABCs <abstract base class>`:
34
114
35
115
.. tabularcolumns :: |l|L|L|L|
36
116
37
- ========================== ====================== ======================= ====================================================
38
- ABC Inherits from Abstract Methods Mixin Methods
39
- ========================== ====================== ======================= ====================================================
40
- :class: `Container ` ``__contains__ ``
41
- :class: `Hashable ` ``__hash__ ``
42
- :class: `Iterable ` ``__iter__ ``
43
- :class: `Iterator ` :class: `Iterable ` ``__next__ `` ``__iter__ ``
44
- :class: `Reversible ` :class: `Iterable ` ``__reversed__ ``
45
- :class: `Generator ` :class: `Iterator ` ``send ``, ``throw `` ``close ``, ``__iter__ ``, ``__next__ ``
46
- :class: `Sized ` ``__len__ ``
47
- :class: `Callable ` ``__call__ ``
48
- :class: `Collection ` :class: `Sized `, ``__contains__ ``,
49
- :class: `Iterable `, ``__iter__ ``,
50
- :class: `Container ` ``__len__ ``
51
-
52
- :class:`Sequence` :class:`Reversible`, ``__getitem__``, ``__contains__``, ``__iter__``, ``__reversed__``,
53
- :class: `Collection ` ``__len__ `` ``index ``, and ``count ``
54
-
55
- :class:`MutableSequence` :class:`Sequence` ``__getitem__``, Inherited :class:`Sequence` methods and
56
- ``__setitem__ ``, ``append ``, ``reverse ``, ``extend ``, ``pop ``,
57
- ``__delitem__ ``, ``remove ``, and ``__iadd__ ``
58
- ``__len__ ``,
59
- ``insert ``
60
-
61
- :class:`ByteString` :class:`Sequence` ``__getitem__``, Inherited :class:`Sequence` methods
62
- ``__len__ ``
63
-
64
- :class:`Set` :class:`Collection` ``__contains__``, ``__le__``, ``__lt__``, ``__eq__``, ``__ne__``,
65
- ``__iter__ ``, ``__gt__ ``, ``__ge__ ``, ``__and__ ``, ``__or__ ``,
66
- ``__len__ `` ``__sub__ ``, ``__xor__ ``, and ``isdisjoint ``
67
-
68
- :class:`MutableSet` :class:`Set` ``__contains__``, Inherited :class:`Set` methods and
69
- ``__iter__ ``, ``clear ``, ``pop ``, ``remove ``, ``__ior__ ``,
70
- ``__len__ ``, ``__iand__ ``, ``__ixor__ ``, and ``__isub__ ``
71
- ``add ``,
72
- ``discard ``
73
-
74
- :class:`Mapping` :class:`Collection` ``__getitem__``, ``__contains__``, ``keys``, ``items``, ``values``,
75
- ``__iter__ ``, ``get ``, ``__eq__ ``, and ``__ne__ ``
76
- ``__len__ ``
77
-
78
- :class:`MutableMapping` :class:`Mapping` ``__getitem__``, Inherited :class:`Mapping` methods and
79
- ``__setitem__ ``, ``pop ``, ``popitem ``, ``clear ``, ``update ``,
80
- ``__delitem__ ``, and ``setdefault ``
81
- ``__iter__ ``,
82
- ``__len__ ``
83
-
84
-
85
- :class:`MappingView` :class:`Sized` ``__len__``
86
- :class: `ItemsView ` :class: `MappingView `, ``__contains__ ``,
87
- :class: `Set ` ``__iter__ ``
88
- :class: `KeysView ` :class: `MappingView `, ``__contains__ ``,
89
- :class: `Set ` ``__iter__ ``
90
- :class: `ValuesView ` :class: `MappingView `, ``__contains__ ``, ``__iter__ ``
91
- :class: `Collection `
92
- :class: `Awaitable ` ``__await__ ``
93
- :class: `Coroutine ` :class: `Awaitable ` ``send ``, ``throw `` ``close ``
94
- :class: `AsyncIterable ` ``__aiter__ ``
95
- :class: `AsyncIterator ` :class: `AsyncIterable ` ``__anext__ `` ``__aiter__ ``
96
- :class: `AsyncGenerator ` :class: `AsyncIterator ` ``asend ``, ``athrow `` ``aclose ``, ``__aiter__ ``, ``__anext__ ``
97
- ========================== ====================== ======================= ====================================================
117
+ ============================== ====================== ======================= ====================================================
118
+ ABC Inherits from Abstract Methods Mixin Methods
119
+ ============================== ====================== ======================= ====================================================
120
+ :class: `Container ` [1 ]_ ``__contains__ ``
121
+ :class: `Hashable ` [1 ]_ ``__hash__ ``
122
+ :class: `Iterable ` [1 ]_ [2 ]_ ``__iter__ ``
123
+ :class: `Iterator ` [1 ]_ :class: `Iterable ` ``__next__ `` ``__iter__ ``
124
+ :class: `Reversible ` [1 ]_ :class: `Iterable ` ``__reversed__ ``
125
+ :class: `Generator ` [1 ]_ :class: `Iterator ` ``send ``, ``throw `` ``close ``, ``__iter__ ``, ``__next__ ``
126
+ :class: `Sized ` [1 ]_ ``__len__ ``
127
+ :class: `Callable ` [1 ]_ ``__call__ ``
128
+ :class: `Collection ` [1 ]_ :class: `Sized `, ``__contains__ ``,
129
+ :class: `Iterable `, ``__iter__ ``,
130
+ :class: `Container ` ``__len__ ``
131
+
132
+ :class:`Sequence` :class:`Reversible`, ``__getitem__``, ``__contains__``, ``__iter__``, ``__reversed__``,
133
+ :class: `Collection ` ``__len__ `` ``index ``, and ``count ``
134
+
135
+ :class:`MutableSequence` :class:`Sequence` ``__getitem__``, Inherited :class:`Sequence` methods and
136
+ ``__setitem__ ``, ``append ``, ``reverse ``, ``extend ``, ``pop ``,
137
+ ``__delitem__ ``, ``remove ``, and ``__iadd__ ``
138
+ ``__len__ ``,
139
+ ``insert ``
140
+
141
+ :class:`ByteString` :class:`Sequence` ``__getitem__``, Inherited :class:`Sequence` methods
142
+ ``__len__ ``
143
+
144
+ :class:`Set` :class:`Collection` ``__contains__``, ``__le__``, ``__lt__``, ``__eq__``, ``__ne__``,
145
+ ``__iter__ ``, ``__gt__ ``, ``__ge__ ``, ``__and__ ``, ``__or__ ``,
146
+ ``__len__ `` ``__sub__ ``, ``__xor__ ``, and ``isdisjoint ``
147
+
148
+ :class:`MutableSet` :class:`Set` ``__contains__``, Inherited :class:`Set` methods and
149
+ ``__iter__ ``, ``clear ``, ``pop ``, ``remove ``, ``__ior__ ``,
150
+ ``__len__ ``, ``__iand__ ``, ``__ixor__ ``, and ``__isub__ ``
151
+ ``add ``,
152
+ ``discard ``
153
+
154
+ :class:`Mapping` :class:`Collection` ``__getitem__``, ``__contains__``, ``keys``, ``items``, ``values``,
155
+ ``__iter__ ``, ``get ``, ``__eq__ ``, and ``__ne__ ``
156
+ ``__len__ ``
157
+
158
+ :class:`MutableMapping` :class:`Mapping` ``__getitem__``, Inherited :class:`Mapping` methods and
159
+ ``__setitem__ ``, ``pop ``, ``popitem ``, ``clear ``, ``update ``,
160
+ ``__delitem__ ``, and ``setdefault ``
161
+ ``__iter__ ``,
162
+ ``__len__ ``
163
+
164
+
165
+ :class:`MappingView` :class:`Sized` ``__len__``
166
+ :class: `ItemsView ` :class: `MappingView `, ``__contains__ ``,
167
+ :class: `Set ` ``__iter__ ``
168
+ :class: `KeysView ` :class: `MappingView `, ``__contains__ ``,
169
+ :class: `Set ` ``__iter__ ``
170
+ :class: `ValuesView ` :class: `MappingView `, ``__contains__ ``, ``__iter__ ``
171
+ :class: `Collection `
172
+ :class: `Awaitable ` [1 ]_ ``__await__ ``
173
+ :class: `Coroutine ` [1 ]_ :class: `Awaitable ` ``send ``, ``throw `` ``close ``
174
+ :class: `AsyncIterable ` [1 ]_ ``__aiter__ ``
175
+ :class: `AsyncIterator ` [1 ]_ :class: `AsyncIterable ` ``__anext__ `` ``__aiter__ ``
176
+ :class: `AsyncGenerator ` [1 ]_ :class: `AsyncIterator ` ``asend ``, ``athrow `` ``aclose ``, ``__aiter__ ``, ``__anext__ ``
177
+ ============================== ====================== ======================= ====================================================
178
+
179
+
180
+ .. rubric :: Footnotes
181
+
182
+ .. [1 ] These ABCs override :meth: `object.__subclasshook__ ` to support
183
+ testing an interface by verifying the required methods are present
184
+ and have not been set to :const: `None `. This only works for simple
185
+ interfaces. More complex interfaces require registration or direct
186
+ subclassing.
187
+
188
+ .. [2 ] Checking ``isinstance(obj, Iterable) `` detects classes that are
189
+ registered as :class: `Iterable ` or that have an :meth: `__iter__ `
190
+ method, but it does not detect classes that iterate with the
191
+ :meth: `__getitem__ ` method. The only reliable way to determine
192
+ whether an object is :term: `iterable ` is to call ``iter(obj) ``.
193
+
194
+
195
+ Collections Abstract Base Classes -- Detailed Descriptions
196
+ ----------------------------------------------------------
98
197
99
198
100
199
.. class :: Container
@@ -244,8 +343,10 @@ ABC Inherits from Abstract Methods Mixin
244
343
245
344
.. versionadded :: 3.6
246
345
346
+ Examples and Recipes
347
+ --------------------
247
348
248
- These ABCs allow us to ask classes or instances if they provide
349
+ ABCs allow us to ask classes or instances if they provide
249
350
particular functionality, for example::
250
351
251
352
size = None
0 commit comments