summaryrefslogtreecommitdiffstats
path: root/Doc/library/collections.abc.rst
blob: ea27436f67f0bfe1d6a73bb9287f852ad1e50795 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
:mod:`!collections.abc` --- Abstract Base Classes for Containers
================================================================

.. module:: collections.abc
   :synopsis: Abstract base classes for containers

.. moduleauthor:: Raymond Hettinger <python at rcn.com>
.. sectionauthor:: Raymond Hettinger <python at rcn.com>

.. versionadded:: 3.3
   Formerly, this module was part of the :mod:`collections` module.

**Source code:** :source:`Lib/_collections_abc.py`

.. testsetup:: *

   from collections.abc import *
   import itertools
   __name__ = '<doctest>'

--------------

This module provides :term:`abstract base classes <abstract base class>` that
can be used to test whether a class provides a particular interface; for
example, whether it is :term:`hashable` or whether it is a :term:`mapping`.

An :func:`issubclass` or :func:`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:

.. testcode::

    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

.. doctest::

   >>> 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 :func:`issubclass` or :func:`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:

.. testcode::

    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

.. doctest::

   >>> issubclass(D, Sequence)
   True
   >>> isinstance(D(), Sequence)
   True

In this example, class :class:`!D` does not need to define
``__contains__``, ``__iter__``, and ``__reversed__`` because the
:ref:`in-operator <comparisons>`, the :term:`iteration <iterable>`
logic, and the :func:`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
:const:`None`):

.. testcode::

    class E:
        def __iter__(self): ...
        def __next__(self): ...

.. doctest::

   >>> 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 :class:`Sequence` from
a :class:`Mapping`.

.. versionadded:: 3.9
   These abstract classes now support ``[]``. See :ref:`types-genericalias`
   and :pep:`585`.

.. _collections-abstract-base-classes:

Collections Abstract Base Classes
---------------------------------

The collections module offers the following :term:`ABCs <abstract base class>`:

.. tabularcolumns:: |l|L|L|L|

============================== ====================== ======================= ====================================================
ABC                            Inherits from          Abstract Methods        Mixin Methods
============================== ====================== ======================= ====================================================
:class:`Container` [1]_                               ``__contains__``
:class:`Hashable` [1]_                                ``__hash__``
:class:`Iterable` [1]_ [2]_                           ``__iter__``
:class:`Iterator` [1]_         :class:`Iterable`      ``__next__``            ``__iter__``
:class:`Reversible` [1]_       :class:`Iterable`      ``__reversed__``
:class:`Generator`  [1]_       :class:`Iterator`      ``send``, ``throw``     ``close``, ``__iter__``, ``__next__``
:class:`Sized`  [1]_                                  ``__len__``
:class:`Callable`  [1]_                               ``__call__``
:class:`Collection`  [1]_      :class:`Sized`,        ``__contains__``,
                               :class:`Iterable`,     ``__iter__``,
                               :class:`Container`     ``__len__``

:class:`Sequence`              :class:`Reversible`,   ``__getitem__``,        ``__contains__``, ``__iter__``, ``__reversed__``,
                               :class:`Collection`    ``__len__``             ``index``, and ``count``

:class:`MutableSequence`       :class:`Sequence`      ``__getitem__``,        Inherited :class:`Sequence` methods and
                                                      ``__setitem__``,        ``append``, ``clear``, ``reverse``, ``extend``,
                                                      ``__delitem__``,        ``pop``, ``remove``, and ``__iadd__``
                                                      ``__len__``,
                                                      ``insert``

:class:`ByteString`            :class:`Sequence`      ``__getitem__``,        Inherited :class:`Sequence` methods
                                                      ``__len__``

:class:`Set`                   :class:`Collection`    ``__contains__``,       ``__le__``, ``__lt__``, ``__eq__``, ``__ne__``,
                                                      ``__iter__``,           ``__gt__``, ``__ge__``, ``__and__``, ``__or__``,
                                                      ``__len__``             ``__sub__``, ``__xor__``, and ``isdisjoint``

:class:`MutableSet`            :class:`Set`           ``__contains__``,       Inherited :class:`Set` methods and
                                                      ``__iter__``,           ``clear``, ``pop``, ``remove``, ``__ior__``,
                                                      ``__len__``,            ``__iand__``, ``__ixor__``, and ``__isub__``
                                                      ``add``,
                                                      ``discard``

:class:`Mapping`               :class:`Collection`    ``__getitem__``,        ``__contains__``, ``keys``, ``items``, ``values``,
                                                      ``__iter__``,           ``get``, ``__eq__``, and ``__ne__``
                                                      ``__len__``

:class:`MutableMapping`        :class:`Mapping`       ``__getitem__``,        Inherited :class:`Mapping` methods and
                                                      ``__setitem__``,        ``pop``, ``popitem``, ``clear``, ``update``,
                                                      ``__delitem__``,        and ``setdefault``
                                                      ``__iter__``,
                                                      ``__len__``


:class:`MappingView`           :class:`Sized`                                 ``__len__``
:class:`ItemsView`             :class:`MappingView`,                          ``__contains__``,
                               :class:`Set`                                   ``__iter__``
:class:`KeysView`              :class:`MappingView`,                          ``__contains__``,
                               :class:`Set`                                   ``__iter__``
:class:`ValuesView`            :class:`MappingView`,                          ``__contains__``, ``__iter__``
                               :class:`Collection`
:class:`Awaitable` [1]_                               ``__await__``
:class:`Coroutine` [1]_        :class:`Awaitable`     ``send``, ``throw``     ``close``
:class:`AsyncIterable` [1]_                           ``__aiter__``
:class:`AsyncIterator` [1]_    :class:`AsyncIterable` ``__anext__``           ``__aiter__``
:class:`AsyncGenerator` [1]_   :class:`AsyncIterator` ``asend``, ``athrow``   ``aclose``, ``__aiter__``, ``__anext__``
:class:`Buffer` [1]_                                  ``__buffer__``
============================== ====================== ======================= ====================================================


.. rubric:: Footnotes

.. [1] These ABCs override :meth:`~abc.ABCMeta.__subclasshook__` to support
   testing an interface by verifying the required methods are present
   and have not been set to :const:`None`.  This only works for simple
   interfaces.  More complex interfaces require registration or direct
   subclassing.

.. [2] Checking ``isinstance(obj, Iterable)`` detects classes that are
   registered as :class:`Iterable` or that have an :meth:`~container.__iter__`
   method, but it does not detect classes that iterate with the
   :meth:`~object.__getitem__` method.  The only reliable way to determine
   whether an object is :term:`iterable` is to call ``iter(obj)``.


Collections Abstract Base Classes -- Detailed Descriptions
----------------------------------------------------------


.. class:: Container

   ABC for classes that provide the :meth:`~object.__contains__` method.

.. class:: Hashable

   ABC for classes that provide the :meth:`~object.__hash__` method.

.. class:: Sized

   ABC for classes that provide the :meth:`~object.__len__` method.

.. class:: Callable

   ABC for classes that provide the :meth:`~object.__call__` method.

.. class:: Iterable

   ABC for classes that provide the :meth:`~container.__iter__` method.

   Checking ``isinstance(obj, Iterable)`` detects classes that are registered
   as :class:`Iterable` or that have an :meth:`~container.__iter__` method,
   but it does
   not detect classes that iterate with the :meth:`~object.__getitem__` method.
   The only reliable way to determine whether an object is :term:`iterable`
   is to call ``iter(obj)``.

.. class:: Collection

   ABC for sized iterable container classes.

   .. versionadded:: 3.6

.. class:: Iterator

   ABC for classes that provide the :meth:`~iterator.__iter__` and
   :meth:`~iterator.__next__` methods.  See also the definition of
   :term:`iterator`.

.. class:: Reversible

   ABC for iterable classes that also provide the :meth:`~object.__reversed__`
   method.

   .. versionadded:: 3.6

.. class:: Generator

   ABC for :term:`generator` classes that implement the protocol defined in
   :pep:`342` that extends :term:`iterators <iterator>` with the
   :meth:`~generator.send`,
   :meth:`~generator.throw` and :meth:`~generator.close` methods.

   .. versionadded:: 3.5

.. class:: Sequence
           MutableSequence
           ByteString

   ABCs for read-only and mutable :term:`sequences <sequence>`.

   Implementation note: Some of the mixin methods, such as
   :meth:`~container.__iter__`, :meth:`~object.__reversed__` and :meth:`index`, make
   repeated calls to the underlying :meth:`~object.__getitem__` method.
   Consequently, if :meth:`~object.__getitem__` is implemented with constant
   access speed, the mixin methods will have linear performance;
   however, if the underlying method is linear (as it would be with a
   linked list), the mixins will have quadratic performance and will
   likely need to be overridden.

   .. versionchanged:: 3.5
      The index() method added support for *stop* and *start*
      arguments.

   .. deprecated-removed:: 3.12 3.14
      The :class:`ByteString` ABC has been deprecated.
      For use in typing, prefer a union, like ``bytes | bytearray``, or
      :class:`collections.abc.Buffer`.
      For use as an ABC, prefer :class:`Sequence` or :class:`collections.abc.Buffer`.

.. class:: Set
           MutableSet

   ABCs for read-only and mutable :ref:`sets <types-set>`.

.. class:: Mapping
           MutableMapping

   ABCs for read-only and mutable :term:`mappings <mapping>`.

.. class:: MappingView
           ItemsView
           KeysView
           ValuesView

   ABCs for mapping, items, keys, and values :term:`views <dictionary view>`.

.. class:: Awaitable

   ABC for :term:`awaitable` objects, which can be used in :keyword:`await`
   expressions.  Custom implementations must provide the
   :meth:`~object.__await__` method.

   :term:`Coroutine <coroutine>` objects and instances of the
   :class:`~collections.abc.Coroutine` ABC are all instances of this ABC.

   .. note::
      In CPython, generator-based coroutines (:term:`generators <generator>`
      decorated with :func:`@types.coroutine <types.coroutine>`) are
      *awaitables*, even though they do not have an :meth:`~object.__await__` method.
      Using ``isinstance(gencoro, Awaitable)`` for them will return ``False``.
      Use :func:`inspect.isawaitable` to detect them.

   .. versionadded:: 3.5

.. class:: Coroutine

   ABC for :term:`coroutine` compatible classes.  These implement the
   following methods, defined in :ref:`coroutine-objects`:
   :meth:`~coroutine.send`, :meth:`~coroutine.throw`, and
   :meth:`~coroutine.close`.  Custom implementations must also implement
   :meth:`~object.__await__`.  All :class:`Coroutine` instances are also
   instances of :class:`Awaitable`.

   .. note::
      In CPython, generator-based coroutines (:term:`generators <generator>`
      decorated with :func:`@types.coroutine <types.coroutine>`) are
      *awaitables*, even though they do not have an :meth:`~object.__await__` method.
      Using ``isinstance(gencoro, Coroutine)`` for them will return ``False``.
      Use :func:`inspect.isawaitable` to detect them.

   .. versionadded:: 3.5

.. class:: AsyncIterable

   ABC for classes that provide an ``__aiter__`` method.  See also the
   definition of :term:`asynchronous iterable`.

   .. versionadded:: 3.5

.. class:: AsyncIterator

   ABC for classes that provide ``__aiter__`` and ``__anext__``
   methods.  See also the definition of :term:`asynchronous iterator`.

   .. versionadded:: 3.5

.. class:: AsyncGenerator

   ABC for :term:`asynchronous generator` classes that implement the protocol
   defined in :pep:`525` and :pep:`492`.

   .. versionadded:: 3.6

.. class:: Buffer

   ABC for classes that provide the :meth:`~object.__buffer__` method,
   implementing the :ref:`buffer protocol <bufferobjects>`. See :pep:`688`.

   .. versionadded:: 3.12

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)

Several of the ABCs are also useful as mixins that make it easier to develop
classes supporting container APIs.  For example, to write a class supporting
the full :class:`Set` API, it is only necessary to supply the three underlying
abstract methods: :meth:`~object.__contains__`, :meth:`~container.__iter__`, and
:meth:`~object.__len__`. The ABC supplies the remaining methods such as
:meth:`!__and__` and :meth:`~frozenset.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

Notes on using :class:`Set` and :class:`MutableSet` as a mixin:

(1)
   Since some set operations create new sets, the default mixin methods need
   a way to create new instances from an :term:`iterable`. The class constructor is
   assumed to have a signature in the form ``ClassName(iterable)``.
   That assumption is factored-out to an internal :class:`classmethod` called
   :meth:`!_from_iterable` which calls ``cls(iterable)`` to produce a new set.
   If the :class:`Set` mixin is being used in a class with a different
   constructor signature, you will need to override :meth:`!_from_iterable`
   with a classmethod or regular method that can construct new instances from
   an iterable argument.

(2)
   To override the comparisons (presumably for speed, as the
   semantics are fixed), redefine :meth:`~object.__le__` and
   :meth:`~object.__ge__`,
   then the other operations will automatically follow suit.

(3)
   The :class:`Set` mixin provides a :meth:`!_hash` method to compute a hash value
   for the set; however, :meth:`~object.__hash__` is not defined because not all sets
   are :term:`hashable` or immutable.  To add set hashability using mixins,
   inherit from both :meth:`Set` and :meth:`Hashable`, then define
   ``__hash__ = Set._hash``.

.. seealso::

   * `OrderedSet recipe <https://code.activestate.com/recipes/576694/>`_ for an
     example built on :class:`MutableSet`.

   * For more about ABCs, see the :mod:`abc` module and :pep:`3119`.