Convert PEP 201 to reST. (#50)

Note that link to Greg's link at the end is wrong:

Greg Wilson's questionaire on proposed syntax to some CS grad students
http://www.python.org/pipermail/python-dev/2000-July/013139.html

It does not exists. While the archive **do** go to this date.

I believe that woudl be
https://mail.python.org/pipermail/python-dev/2000-July/006427.html

    [Python-Dev] multi-loop quiz results
    Thu, 13 Jul 2000 15:17:41 -0400 (EDT)

    > I gave 20+ grad students in computer engineering and computer
    > science...
This commit is contained in:
Matthias Bussonnier 2016-07-19 14:25:03 -07:00 committed by Berker Peksag
parent 976c962b24
commit 8eff8067cf
1 changed files with 159 additions and 141 deletions

View File

@ -5,47 +5,51 @@ Last-Modified: $Date$
Author: barry@python.org (Barry Warsaw) Author: barry@python.org (Barry Warsaw)
Status: Final Status: Final
Type: Standards Track Type: Standards Track
Content-Type: text/x-rst
Created: 13-Jul-2000 Created: 13-Jul-2000
Python-Version: 2.0 Python-Version: 2.0
Post-History: 27-Jul-2000 Post-History: 27-Jul-2000
Introduction
This PEP describes the `lockstep iteration' proposal. This PEP Introduction
tracks the status and ownership of this feature, slated for ============
introduction in Python 2.0. It contains a description of the
feature and outlines changes necessary to support the feature. This PEP describes the 'lockstep iteration' proposal. This PEP tracks
This PEP summarizes discussions held in mailing list forums, and the status and ownership of this feature, slated for introduction in
provides URLs for further information, where appropriate. The CVS Python 2.0. It contains a description of the feature and outlines
revision history of this file contains the definitive historical changes necessary to support the feature. This PEP summarizes
record. discussions held in mailing list forums, and provides URLs for further
information, where appropriate. The CVS revision history of this file
contains the definitive historical record.
Motivation Motivation
==========
Standard for-loops in Python iterate over every element in a Standard for-loops in Python iterate over every element in a sequence
sequence until the sequence is exhausted[1]. However, for-loops until the sequence is exhausted [1]_. However, for-loops iterate over
iterate over only a single sequence, and it is often desirable to only a single sequence, and it is often desirable to loop over more
loop over more than one sequence in a lock-step fashion. In other than one sequence in a lock-step fashion. In other words, in a way
words, in a way such that nthe i-th iteration through the loop such that the i-th iteration through the loop returns an object
returns an object containing the i-th element from each sequence. containing the i-th element from each sequence.
The common idioms used to accomplish this are unintuitive. This The common idioms used to accomplish this are unintuitive. This PEP
PEP proposes a standard way of performing such iterations by proposes a standard way of performing such iterations by introducing a
introducing a new builtin function called `zip'. new builtin function called ``zip``.
While the primary motivation for zip() comes from lock-step While the primary motivation for zip() comes from lock-step iteration,
iteration, by implementing zip() as a built-in function, it has by implementing zip() as a built-in function, it has additional
additional utility in contexts other than for-loops. utility in contexts other than for-loops.
Lockstep For-Loops Lockstep For-Loops
==================
Lockstep for-loops are non-nested iterations over two or more Lockstep for-loops are non-nested iterations over two or more
sequences, such that at each pass through the loop, one element sequences, such that at each pass through the loop, one element from
from each sequence is taken to compose the target. This behavior each sequence is taken to compose the target. This behavior can
can already be accomplished in Python through the use of the map() already be accomplished in Python through the use of the map() built-
built-in function: in function::
>>> a = (1, 2, 3) >>> a = (1, 2, 3)
>>> b = (4, 5, 6) >>> b = (4, 5, 6)
@ -62,58 +66,61 @@ Lockstep For-Loops
While the map() idiom is a common one in Python, it has several While the map() idiom is a common one in Python, it has several
disadvantages: disadvantages:
- It is non-obvious to programmers without a functional * It is non-obvious to programmers without a functional programming
programming background. background.
- The use of the magic `None' first argument is non-obvious. * The use of the magic ``None`` first argument is non-obvious.
- It has arbitrary, often unintended, and inflexible semantics * It has arbitrary, often unintended, and inflexible semantics when
when the lists are not of the same length: the shorter sequences the lists are not of the same length: the shorter sequences are
are padded with `None'. padded with ``None``::
>>> c = (4, 5, 6, 7) >>> c = (4, 5, 6, 7)
>>> map(None, a, c) >>> map(None, a, c)
[(1, 4), (2, 5), (3, 6), (None, 7)] [(1, 4), (2, 5), (3, 6), (None, 7)]
For these reasons, several proposals were floated in the Python For these reasons, several proposals were floated in the Python 2.0
2.0 beta time frame for syntactic support of lockstep for-loops. beta time frame for syntactic support of lockstep for-loops. Here are
Here are two suggestions: two suggestions::
for x in seq1, y in seq2: for x in seq1, y in seq2:
# stuff # stuff
::
for x, y in seq1, seq2: for x, y in seq1, seq2:
# stuff # stuff
Neither of these forms would work, since they both already mean Neither of these forms would work, since they both already mean
something in Python and changing the meanings would break existing something in Python and changing the meanings would break existing
code. All other suggestions for new syntax suffered the same code. All other suggestions for new syntax suffered the same problem,
problem, or were in conflict with other another proposed feature or were in conflict with other another proposed feature called 'list
called `list comprehensions' (see PEP 202). comprehensions' (see PEP 202).
The Proposed Solution The Proposed Solution
=====================
The proposed solution is to introduce a new built-in sequence The proposed solution is to introduce a new built-in sequence
generator function, available in the __builtin__ module. This generator function, available in the ``__builtin__`` module. This
function is to be called `zip' and has the following signature: function is to be called ``zip`` and has the following signature::
zip(seqa, [seqb, [...]]) zip(seqa, [seqb, [...]])
zip() takes one or more sequences and weaves their elements ``zip()`` takes one or more sequences and weaves their elements
together, just as map(None, ...) does with sequences of equal together, just as ``map(None, ...)`` does with sequences of equal
length. The weaving stops when the shortest sequence is length. The weaving stops when the shortest sequence is exhausted.
exhausted.
Return Value Return Value
============
zip() returns a real Python list, the same way map() does. ``zip()`` returns a real Python list, the same way ``map()`` does.
Examples Examples
========
Here are some examples, based on the reference implementation Here are some examples, based on the reference implementation below::
below.
>>> a = (1, 2, 3, 4) >>> a = (1, 2, 3, 4)
>>> b = (5, 6, 7, 8) >>> b = (5, 6, 7, 8)
@ -129,8 +136,8 @@ Examples
>>> zip(a, b, c, d) >>> zip(a, b, c, d)
[(1, 5, 9, 12), (2, 6, 10, 13)] [(1, 5, 9, 12), (2, 6, 10, 13)]
Note that when the sequences are of the same length, zip() is Note that when the sequences are of the same length, ``zip()`` is
reversible: reversible::
>>> a = (1, 2, 3) >>> a = (1, 2, 3)
>>> b = (4, 5, 6) >>> b = (4, 5, 6)
@ -146,15 +153,16 @@ Examples
>>> x == z >>> x == z
1 1
It is not possible to reverse zip this way when the sequences are It is not possible to reverse zip this way when the sequences are not
not all the same length. all the same length.
Reference Implementation Reference Implementation
========================
Here is a reference implementation, in Python of the zip() Here is a reference implementation, in Python of the zip() built-in
built-in function. This will be replaced with a C implementation function. This will be replaced with a C implementation after final
after final approval. approval::
def zip(*args): def zip(*args):
if not args: if not args:
@ -172,109 +180,119 @@ Reference Implementation
return ret return ret
BDFL Pronouncements BDFL Pronouncements
===================
Note: the BDFL refers to Guido van Rossum, Python's Benevolent Note: the BDFL refers to Guido van Rossum, Python's Benevolent
Dictator For Life. Dictator For Life.
- The function's name. An earlier version of this PEP included an * The function's name. An earlier version of this PEP included an
open issue listing 20+ proposed alternative names to zip(). In open issue listing 20+ proposed alternative names to ``zip()``. In
the face of no overwhelmingly better choice, the BDFL strongly the face of no overwhelmingly better choice, the BDFL strongly
prefers zip() due to its Haskell[2] heritage. See version 1.7 prefers ``zip()`` due to its Haskell [2]_ heritage. See version 1.7
of this PEP for the list of alternatives. of this PEP for the list of alternatives.
- zip() shall be a built-in function. * ``zip()`` shall be a built-in function.
- Optional padding. An earlier version of this PEP proposed an * Optional padding. An earlier version of this PEP proposed an
optional `pad' keyword argument, which would be used when the optional ``pad`` keyword argument, which would be used when the
argument sequences were not the same length. This is similar argument sequences were not the same length. This is similar
behavior to the map(None, ...) semantics except that the user behavior to the ``map(None, ...)`` semantics except that the user
would be able to specify pad object. This has been rejected by would be able to specify pad object. This has been rejected by the
the BDFL in favor of always truncating to the shortest sequence, BDFL in favor of always truncating to the shortest sequence, because
because of the KISS principle. If there's a true need, it is of the KISS principle. If there's a true need, it is easier to add
easier to add later. If it is not needed, it would still be later. If it is not needed, it would still be impossible to delete
impossible to delete it in the future. it in the future.
- Lazy evaluation. An earlier version of this PEP proposed that * Lazy evaluation. An earlier version of this PEP proposed that
zip() return a built-in object that performed lazy evaluation ``zip()`` return a built-in object that performed lazy evaluation
using __getitem__() protocol. This has been strongly rejected using ``__getitem__()`` protocol. This has been strongly rejected
by the BDFL in favor of returning a real Python list. If lazy by the BDFL in favor of returning a real Python list. If lazy
evaluation is desired in the future, the BDFL suggests an xzip() evaluation is desired in the future, the BDFL suggests an ``xzip()``
function be added. function be added.
- zip() with no arguments. the BDFL strongly prefers this raise a * ``zip()`` with no arguments. the BDFL strongly prefers this raise a
TypeError exception. TypeError exception.
- zip() with one argument. the BDFL strongly prefers that this * ``zip()`` with one argument. the BDFL strongly prefers that this
return a list of 1-tuples. return a list of 1-tuples.
- Inner and outer container control. An earlier version of this * Inner and outer container control. An earlier version of this PEP
PEP contains a rather lengthy discussion on a feature that some contains a rather lengthy discussion on a feature that some people
people wanted, namely the ability to control what the inner and wanted, namely the ability to control what the inner and outer
outer container types were (they are tuples and list container types were (they are tuples and list respectively in this
respectively in this version of the PEP). Given the simplified version of the PEP). Given the simplified API and implementation,
API and implementation, this elaboration is rejected. For a this elaboration is rejected. For a more detailed analysis, see
more detailed analysis, see version 1.7 of this PEP. version 1.7 of this PEP.
Subsequent Change to zip() Subsequent Change to ``zip()``
==============================
In Python 2.4, zip() with no arguments was modified to return an In Python 2.4, zip() with no arguments was modified to return an empty
empty list rather than raising a TypeError exception. The rationale list rather than raising a TypeError exception. The rationale for the
for the original behavior was that the absence of arguments was original behavior was that the absence of arguments was thought to
thought to indicate a programming error. However, that thinking indicate a programming error. However, that thinking did not
did not anticipate the use of zip() with the * operator for unpacking anticipate the use of zip() with the ``*`` operator for unpacking
variable length argument lists. For example, the inverse of zip variable length argument lists. For example, the inverse of zip could
could be defined as: unzip = lambda s: zip(*s). That transformation be defined as: ``unzip = lambda s: zip(*s)``. That transformation
also defines a matrix transpose or an equivalent row/column swap for also defines a matrix transpose or an equivalent row/column swap for
tables defined as lists of tuples. The latter transformation is tables defined as lists of tuples. The latter transformation is
commonly used when reading data files with records as rows and fields commonly used when reading data files with records as rows and fields
as columns. For example, the code: as columns. For example, the code::
date, rain, high, low = zip(*csv.reader(file("weather.csv"))) date, rain, high, low = zip(*csv.reader(file("weather.csv")))
rearranges columnar data so that each field is collected into rearranges columnar data so that each field is collected into
individual tuples for straightforward looping and summarization: individual tuples for straightforward looping and summarization::
print "Total rainfall", sum(rain) print "Total rainfall", sum(rain)
Using zip(*args) is more easily coded if zip(*[]) is handled as an Using ``zip(*args)`` is more easily coded if ``zip(*[])`` is handled
allowable case rather than an exception. This is especially helpful as an allowable case rather than an exception. This is especially
when data is either built up from or recursed down to a null case helpful when data is either built up from or recursed down to a null
with no records. case with no records.
Seeing this possibility, the BDFL agreed (with some misgivings) to Seeing this possibility, the BDFL agreed (with some misgivings) to
have the behavior changed for Py2.4. have the behavior changed for Py2.4.
Other Changes Other Changes
=============
- The xzip() function discussed above was implemented in Py2.3 in * The ``xzip()`` function discussed above was implemented in Py2.3 in
the itertools module as itertools.izip(). This function provides the ``itertools`` module as ``itertools.izip()``. This function
lazy behavior, consuming single elements and producing a single provides lazy behavior, consuming single elements and producing a
tuple on each pass. The "just-in-time" style saves memory and single tuple on each pass. The "just-in-time" style saves memory
runs faster than its list based counterpart, zip(). and runs faster than its list based counterpart, ``zip()``.
- The itertools module also added itertools.repeat() and * The ``itertools`` module also added ``itertools.repeat()`` and
itertools.chain(). These tools can be used together to pad ``itertools.chain()``. These tools can be used together to pad
sequences with None (to match the behavior of map(None, seqn)): sequences with ``None`` (to match the behavior of ``map(None,
seqn)``)::
zip(firstseq, chain(secondseq, repeat(None))) zip(firstseq, chain(secondseq, repeat(None)))
References References
==========
.. [1] http://docs.python.org/reference/compound_stmts.html#for
.. [2] http://www.haskell.org/onlinereport/standard-prelude.html#$vzip
[1] http://docs.python.org/reference/compound_stmts.html#for
[2] http://www.haskell.org/onlinereport/standard-prelude.html#$vzip
Greg Wilson's questionaire on proposed syntax to some CS grad students Greg Wilson's questionaire on proposed syntax to some CS grad students
http://www.python.org/pipermail/python-dev/2000-July/013139.html http://www.python.org/pipermail/python-dev/2000-July/013139.html
Copyright Copyright
=========
This document has been placed in the public domain. This document has been placed in the public domain.
..
Local Variables: Local Variables:
mode: indented-text mode: indented-text
indent-tabs-mode: nil indent-tabs-mode: nil