Skip to content

Commit 59cf853

Browse files
authored
bpo-40636: Documentation for zip-strict (#20961)
1 parent 3358da4 commit 59cf853

File tree

2 files changed

+87
-44
lines changed

2 files changed

+87
-44
lines changed

Doc/library/functions.rst

Lines changed: 84 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,50 +1720,90 @@ are always available. They are listed here in alphabetical order.
17201720
dictionary are ignored.
17211721

17221722

1723-
.. function:: zip(*iterables)
1724-
1725-
Make an iterator that aggregates elements from each of the iterables.
1726-
1727-
Returns an iterator of tuples, where the *i*-th tuple contains
1728-
the *i*-th element from each of the argument sequences or iterables. The
1729-
iterator stops when the shortest input iterable is exhausted. With a single
1730-
iterable argument, it returns an iterator of 1-tuples. With no arguments,
1731-
it returns an empty iterator. Equivalent to::
1732-
1733-
def zip(*iterables):
1734-
# zip('ABCD', 'xy') --> Ax By
1735-
sentinel = object()
1736-
iterators = [iter(it) for it in iterables]
1737-
while iterators:
1738-
result = []
1739-
for it in iterators:
1740-
elem = next(it, sentinel)
1741-
if elem is sentinel:
1742-
return
1743-
result.append(elem)
1744-
yield tuple(result)
1745-
1746-
The left-to-right evaluation order of the iterables is guaranteed. This
1747-
makes possible an idiom for clustering a data series into n-length groups
1748-
using ``zip(*[iter(s)]*n)``. This repeats the *same* iterator ``n`` times
1749-
so that each output tuple has the result of ``n`` calls to the iterator.
1750-
This has the effect of dividing the input into n-length chunks.
1751-
1752-
:func:`zip` should only be used with unequal length inputs when you don't
1753-
care about trailing, unmatched values from the longer iterables. If those
1754-
values are important, use :func:`itertools.zip_longest` instead.
1755-
1756-
:func:`zip` in conjunction with the ``*`` operator can be used to unzip a
1757-
list::
1758-
1759-
>>> x = [1, 2, 3]
1760-
>>> y = [4, 5, 6]
1761-
>>> zipped = zip(x, y)
1762-
>>> list(zipped)
1763-
[(1, 4), (2, 5), (3, 6)]
1764-
>>> x2, y2 = zip(*zip(x, y))
1765-
>>> x == list(x2) and y == list(y2)
1766-
True
1723+
.. function:: zip(*iterables, strict=False)
1724+
1725+
Iterate over several iterables in parallel, producing tuples with an item
1726+
from each one.
1727+
1728+
Example::
1729+
1730+
>>> for item in zip([1, 2, 3], ['sugar', 'spice', 'everything nice']):
1731+
... print(item)
1732+
...
1733+
(1, 'sugar')
1734+
(2, 'spice')
1735+
(3, 'everything nice')
1736+
1737+
More formally: :func:`zip` returns an iterator of tuples, where the *i*-th
1738+
tuple contains the *i*-th element from each of the argument iterables.
1739+
1740+
Another way to think of :func:`zip` is that it turns rows into columns, and
1741+
columns into rows. This is similar to `transposing a matrix
1742+
<https://en.wikipedia.org/wiki/Transpose>`_.
1743+
1744+
:func:`zip` is lazy: The elements won't be processed until the iterable is
1745+
iterated on, e.g. by a :keyword:`!for` loop or by wrapping in a
1746+
:class:`list`.
1747+
1748+
One thing to consider is that the iterables passed to :func:`zip` could have
1749+
different lengths; sometimes by design, and sometimes because of a bug in
1750+
the code that prepared these iterables. Python offers three different
1751+
approaches to dealing with this issue:
1752+
1753+
* By default, :func:`zip` stops when the shortest iterable is exhausted.
1754+
It will ignore the remaining items in the longer iterables, cutting off
1755+
the result to the length of the shortest iterable::
1756+
1757+
>>> list(zip(range(3), ['fee', 'fi', 'fo', 'fum']))
1758+
[(0, 'fee'), (1, 'fi'), (2, 'fo')]
1759+
1760+
* :func:`zip` is often used in cases where the iterables are assumed to be
1761+
of equal length. In such cases, it's recommended to use the ``strict=True``
1762+
option. Its output is the same as regular :func:`zip`::
1763+
1764+
>>> list(zip(('a', 'b', 'c'), (1, 2, 3), strict=True))
1765+
[('a', 1), ('b', 2), ('c', 3)]
1766+
1767+
Unlike the default behavior, it checks that the lengths of iterables are
1768+
identical, raising a :exc:`ValueError` if they aren't:
1769+
1770+
>>> list(zip(range(3), ['fee', 'fi', 'fo', 'fum'], strict=True))
1771+
Traceback (most recent call last):
1772+
...
1773+
ValueError: zip() argument 2 is longer than argument 1
1774+
1775+
Without the ``strict=True`` argument, any bug that results in iterables of
1776+
different lengths will be silenced, possibly mainfesting as a hard-to-find
1777+
bug in another part of the program.
1778+
1779+
* Shorter iterables can be padded with a constant value to make all the
1780+
iterables have the same length. This is done by
1781+
:func:`itertools.zip_longest`.
1782+
1783+
Edge cases: With a single iterable argument, :func:`zip` returns an
1784+
iterator of 1-tuples. With no arguments, it returns an empty iterator.
1785+
1786+
Tips and tricks:
1787+
1788+
* The left-to-right evaluation order of the iterables is guaranteed. This
1789+
makes possible an idiom for clustering a data series into n-length groups
1790+
using ``zip(*[iter(s)]*n, strict=True)``. This repeats the *same* iterator
1791+
``n`` times so that each output tuple has the result of ``n`` calls to the
1792+
iterator. This has the effect of dividing the input into n-length chunks.
1793+
1794+
* :func:`zip` in conjunction with the ``*`` operator can be used to unzip a
1795+
list::
1796+
1797+
>>> x = [1, 2, 3]
1798+
>>> y = [4, 5, 6]
1799+
>>> list(zip(x, y))
1800+
[(1, 4), (2, 5), (3, 6)]
1801+
>>> x2, y2 = zip(*zip(x, y))
1802+
>>> x == list(x2) and y == list(y2)
1803+
True
1804+
1805+
.. versionchanged:: 3.10
1806+
Added the ``strict`` argument.
17671807

17681808

17691809
.. function:: __import__(name, globals=None, locals=None, fromlist=(), level=0)

Doc/whatsnew/3.10.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ New Features
7979
:class:`types.MappingProxyType` object wrapping the original
8080
dictionary. (Contributed by Dennis Sweeney in :issue:`40890`.)
8181

82+
* :pep:`618`: The :func:`zip` function now has an optional ``strict`` flag, used
83+
to require that all the iterables have an equal length.
84+
8285

8386
Other Language Changes
8487
======================

0 commit comments

Comments
 (0)