mirror of https://github.com/python/cpython
bpo-40636: Documentation for zip-strict (#20961)
This commit is contained in:
parent
3358da4054
commit
59cf853332
|
@ -1720,51 +1720,91 @@ are always available. They are listed here in alphabetical order.
|
||||||
dictionary are ignored.
|
dictionary are ignored.
|
||||||
|
|
||||||
|
|
||||||
.. function:: zip(*iterables)
|
.. function:: zip(*iterables, strict=False)
|
||||||
|
|
||||||
Make an iterator that aggregates elements from each of the iterables.
|
Iterate over several iterables in parallel, producing tuples with an item
|
||||||
|
from each one.
|
||||||
|
|
||||||
Returns an iterator of tuples, where the *i*-th tuple contains
|
Example::
|
||||||
the *i*-th element from each of the argument sequences or iterables. The
|
|
||||||
iterator stops when the shortest input iterable is exhausted. With a single
|
|
||||||
iterable argument, it returns an iterator of 1-tuples. With no arguments,
|
|
||||||
it returns an empty iterator. Equivalent to::
|
|
||||||
|
|
||||||
def zip(*iterables):
|
>>> for item in zip([1, 2, 3], ['sugar', 'spice', 'everything nice']):
|
||||||
# zip('ABCD', 'xy') --> Ax By
|
... print(item)
|
||||||
sentinel = object()
|
...
|
||||||
iterators = [iter(it) for it in iterables]
|
(1, 'sugar')
|
||||||
while iterators:
|
(2, 'spice')
|
||||||
result = []
|
(3, 'everything nice')
|
||||||
for it in iterators:
|
|
||||||
elem = next(it, sentinel)
|
|
||||||
if elem is sentinel:
|
|
||||||
return
|
|
||||||
result.append(elem)
|
|
||||||
yield tuple(result)
|
|
||||||
|
|
||||||
The left-to-right evaluation order of the iterables is guaranteed. This
|
More formally: :func:`zip` returns an iterator of tuples, where the *i*-th
|
||||||
|
tuple contains the *i*-th element from each of the argument iterables.
|
||||||
|
|
||||||
|
Another way to think of :func:`zip` is that it turns rows into columns, and
|
||||||
|
columns into rows. This is similar to `transposing a matrix
|
||||||
|
<https://en.wikipedia.org/wiki/Transpose>`_.
|
||||||
|
|
||||||
|
:func:`zip` is lazy: The elements won't be processed until the iterable is
|
||||||
|
iterated on, e.g. by a :keyword:`!for` loop or by wrapping in a
|
||||||
|
:class:`list`.
|
||||||
|
|
||||||
|
One thing to consider is that the iterables passed to :func:`zip` could have
|
||||||
|
different lengths; sometimes by design, and sometimes because of a bug in
|
||||||
|
the code that prepared these iterables. Python offers three different
|
||||||
|
approaches to dealing with this issue:
|
||||||
|
|
||||||
|
* By default, :func:`zip` stops when the shortest iterable is exhausted.
|
||||||
|
It will ignore the remaining items in the longer iterables, cutting off
|
||||||
|
the result to the length of the shortest iterable::
|
||||||
|
|
||||||
|
>>> list(zip(range(3), ['fee', 'fi', 'fo', 'fum']))
|
||||||
|
[(0, 'fee'), (1, 'fi'), (2, 'fo')]
|
||||||
|
|
||||||
|
* :func:`zip` is often used in cases where the iterables are assumed to be
|
||||||
|
of equal length. In such cases, it's recommended to use the ``strict=True``
|
||||||
|
option. Its output is the same as regular :func:`zip`::
|
||||||
|
|
||||||
|
>>> list(zip(('a', 'b', 'c'), (1, 2, 3), strict=True))
|
||||||
|
[('a', 1), ('b', 2), ('c', 3)]
|
||||||
|
|
||||||
|
Unlike the default behavior, it checks that the lengths of iterables are
|
||||||
|
identical, raising a :exc:`ValueError` if they aren't:
|
||||||
|
|
||||||
|
>>> list(zip(range(3), ['fee', 'fi', 'fo', 'fum'], strict=True))
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: zip() argument 2 is longer than argument 1
|
||||||
|
|
||||||
|
Without the ``strict=True`` argument, any bug that results in iterables of
|
||||||
|
different lengths will be silenced, possibly mainfesting as a hard-to-find
|
||||||
|
bug in another part of the program.
|
||||||
|
|
||||||
|
* Shorter iterables can be padded with a constant value to make all the
|
||||||
|
iterables have the same length. This is done by
|
||||||
|
:func:`itertools.zip_longest`.
|
||||||
|
|
||||||
|
Edge cases: With a single iterable argument, :func:`zip` returns an
|
||||||
|
iterator of 1-tuples. With no arguments, it returns an empty iterator.
|
||||||
|
|
||||||
|
Tips and tricks:
|
||||||
|
|
||||||
|
* The left-to-right evaluation order of the iterables is guaranteed. This
|
||||||
makes possible an idiom for clustering a data series into n-length groups
|
makes possible an idiom for clustering a data series into n-length groups
|
||||||
using ``zip(*[iter(s)]*n)``. This repeats the *same* iterator ``n`` times
|
using ``zip(*[iter(s)]*n, strict=True)``. This repeats the *same* iterator
|
||||||
so that each output tuple has the result of ``n`` calls to the iterator.
|
``n`` times so that each output tuple has the result of ``n`` calls to the
|
||||||
This has the effect of dividing the input into n-length chunks.
|
iterator. This has the effect of dividing the input into n-length chunks.
|
||||||
|
|
||||||
:func:`zip` should only be used with unequal length inputs when you don't
|
* :func:`zip` in conjunction with the ``*`` operator can be used to unzip a
|
||||||
care about trailing, unmatched values from the longer iterables. If those
|
|
||||||
values are important, use :func:`itertools.zip_longest` instead.
|
|
||||||
|
|
||||||
:func:`zip` in conjunction with the ``*`` operator can be used to unzip a
|
|
||||||
list::
|
list::
|
||||||
|
|
||||||
>>> x = [1, 2, 3]
|
>>> x = [1, 2, 3]
|
||||||
>>> y = [4, 5, 6]
|
>>> y = [4, 5, 6]
|
||||||
>>> zipped = zip(x, y)
|
>>> list(zip(x, y))
|
||||||
>>> list(zipped)
|
|
||||||
[(1, 4), (2, 5), (3, 6)]
|
[(1, 4), (2, 5), (3, 6)]
|
||||||
>>> x2, y2 = zip(*zip(x, y))
|
>>> x2, y2 = zip(*zip(x, y))
|
||||||
>>> x == list(x2) and y == list(y2)
|
>>> x == list(x2) and y == list(y2)
|
||||||
True
|
True
|
||||||
|
|
||||||
|
.. versionchanged:: 3.10
|
||||||
|
Added the ``strict`` argument.
|
||||||
|
|
||||||
|
|
||||||
.. function:: __import__(name, globals=None, locals=None, fromlist=(), level=0)
|
.. function:: __import__(name, globals=None, locals=None, fromlist=(), level=0)
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,9 @@ New Features
|
||||||
:class:`types.MappingProxyType` object wrapping the original
|
:class:`types.MappingProxyType` object wrapping the original
|
||||||
dictionary. (Contributed by Dennis Sweeney in :issue:`40890`.)
|
dictionary. (Contributed by Dennis Sweeney in :issue:`40890`.)
|
||||||
|
|
||||||
|
* :pep:`618`: The :func:`zip` function now has an optional ``strict`` flag, used
|
||||||
|
to require that all the iterables have an equal length.
|
||||||
|
|
||||||
|
|
||||||
Other Language Changes
|
Other Language Changes
|
||||||
======================
|
======================
|
||||||
|
|
Loading…
Reference in New Issue