James's last update, and mark this PEP rejected.

This commit is contained in:
Barry Warsaw 2002-03-11 17:40:50 +00:00
parent 73238e3409
commit e4dbb1a74a
1 changed files with 113 additions and 95 deletions

View File

@ -3,7 +3,7 @@ Title: Simple Iterator for ints
Version: $Revision$ Version: $Revision$
Last-Modified: $Date$ Last-Modified: $Date$
Author: james_althoff@i2.com (Jim Althoff) Author: james_althoff@i2.com (Jim Althoff)
Status: Draft Status: Rejected
Type: Standards Track Type: Standards Track
Created: 12-Nov-2001 Created: 12-Nov-2001
Python-Version: 2.3 Python-Version: 2.3
@ -97,13 +97,13 @@ Rationale
indexed for-loop idiom is to use the builtin range() or xrange() indexed for-loop idiom is to use the builtin range() or xrange()
function to generate a sequence of indices as in, for example: function to generate a sequence of indices as in, for example:
for rowcount in range(table.getRowCount()): for rowcount in range(table.getRowCount()):
print table.getValueAt(rowcount, 0) print table.getValueAt(rowcount, 0)
or or
for rowcount in xrange(table.getRowCount()): for rowcount in xrange(table.getRowCount()):
print table.getValueAt(rowcount, 0) print table.getValueAt(rowcount, 0)
From time to time there are discussions in the Python community From time to time there are discussions in the Python community
about the indexed for-loop idiom. It is sometimes argued that the about the indexed for-loop idiom. It is sometimes argued that the
@ -161,8 +161,8 @@ Rationale
would enable by default the following shortcut for the indexed would enable by default the following shortcut for the indexed
for-loop idiom: for-loop idiom:
for rowcount in table.getRowCount(): for rowcount in table.getRowCount():
print table.getValueAt(rowcount, 0) print table.getValueAt(rowcount, 0)
The following benefits for this approach vis-a-vis the current The following benefits for this approach vis-a-vis the current
mechanism of using the range() or xrange() functions are claimed mechanism of using the range() or xrange() functions are claimed
@ -190,10 +190,6 @@ Rationale
included (as of Python 2.1) for other builtin types such as: included (as of Python 2.1) for other builtin types such as:
lists, tuples, dictionaries, strings, and files. lists, tuples, dictionaries, strings, and files.
Preliminary discussion on the Python interest mailing list
suggests a reasonable amount of initial support for this PEP
(along with some dissents/issues noted below).
Backwards Compatibility Backwards Compatibility
@ -210,8 +206,8 @@ Backwards Compatibility
1) The common case where one forgets to include range() or 1) The common case where one forgets to include range() or
xrange(), for example: xrange(), for example:
for rowcount in table.getRowCount(): for rowcount in table.getRowCount():
print table.getValueAt(rowcount, 0) print table.getValueAt(rowcount, 0)
in Python 2.2 raises a TypeError exception. in Python 2.2 raises a TypeError exception.
@ -238,11 +234,32 @@ Backwards Compatibility
relatively easy to correct should it happen. relatively easy to correct should it happen.
Issues: Issues:
Based on some preliminary discussion on the Python interest Extensive discussions concerning PEP 276 on the Python interest
mailing list, the following concerns have been voiced: mailing list suggests a range of opinions: some in favor, some
neutral, some against. Those in favor tend to agree with the
claims above of the usefulness, convenience, ease of learning,
and simplicity of a simple iterator for integers.
Issues with PEP 276 include:
- Using range/xrange is fine as is.
Response: Some posters feel this way. Other disagree.
- Some feel that iterating over the sequence "0, 1, 2, ..., n-1"
for an integer n is not intuitive. "for i in 5:" is considered
(by some) to be "non-obvious", for example. Some dislike this
usage because it doesn't have "the right feel". Some dislike it
because they believe that this type of usage forces one to view
integers as a sequences and this seems wrong to them. Some
dislike it because they prefer to view for-loops as dealing
with explicit sequences rather than with arbitrary iterators.
Response: Some like the proposed idiom and see it as simple,
elegant, easy to learn, and easy to use. Some are neutral on
this issue. Others, as noted, dislike it.
- Is it obvious that iter(5) maps to the sequence 0,1,2,3,4? - Is it obvious that iter(5) maps to the sequence 0,1,2,3,4?
@ -250,17 +267,12 @@ Issues:
convention for indexing sequences starting at 0 and stopping at convention for indexing sequences starting at 0 and stopping at
(inclusively) the index whose value is one less than the length (inclusively) the index whose value is one less than the length
of the sequence, it is argued that the proposed sequence is of the sequence, it is argued that the proposed sequence is
reasonably intuitive to a Python programmer while being useful reasonably intuitive to the Python programmer while being useful
and practical. and practical. More importantly, it is argued that once learned
this convention is very easy to remember. Note that the doc
- "in" (as in "for i in x") does not match standard English usage string for the range function makes a reference to the
in this case. "up to" or something similar might be better. natural and useful association between range(n) and the indices
for a list whose length is n.
Response: Not everyone felt that matching standard English
perfectly is a requirement. It is noted that "for:else:"
doesn't match standard English very well either. And few are
excited about adding a new keyword, especially just to get a
somewhat better match to standard English usage.
- Possible ambiguity - Possible ambiguity
@ -268,104 +280,110 @@ Issues:
might be mistaken for might be mistaken for
for i in (10,): print i for i in (10,): print i
Response: The predicted ambiguity was not readily apparent to Response: This is exactly the same situation with strings in
several of the posters. current Python (replace 10 with 'spam' in the above, for
example).
- It would be better to add special new syntax such as: - Too general: in the newest releases of Python there are
contexts -- as with for-loops -- where iterators are called
implicitly. Some fear that having an iterator invoked for
an integer in one of the context (excluding for-loops) might
lead to unexpected behavior and bugs. The "x, = 1" example
noted above is an a case in point.
for i in 0..10: print i Response: From the author's perspective the examples of the
above that were identified in the PEP 276 discussions did
not appear to be ones that would be accidentally misused
in ways that would lead to subtle and hard-to-detect errors.
Response: There are other PEPs that take this approach[2][3]. In addition, it seems that there is a way to deal with this
issue by using a variation of what is outlined in the
specification section of this proposal. Instead of adding
an __iter__ method to class int, change the for-loop handling
code to convert (in essense) from
- It would be better to reuse the ellipsis literal syntax (...) for i in n: # when isinstance(n,int) is 1
Response: Shares disadvantages of other proposals that require to
changes to the syntax. Needs more design to determine how it
would handle the general case of start,stop,step,
open/closed/half-closed intervals, etc. Needs a PEP.
- It would be better to reuse the slicing literal syntax attached for i in xrange(n):
to the int class, e.g., int[0:10]
Response: Same as previous response. In addition, design This approach gives the same results in a for-loop as an
consideration needs to be given to what it would mean if one __iter__ method would but would prevent iteration on integer
uses slicing syntax after some arbitrary class other than class values in any other context. Lists and tuples, for example,
int. Needs a PEP. don't have __iter__ and are handled with special code.
Integer values would be one more special case.
- "i in n" seems very unnatural.
Response: Some feel that "i in len(mylist)" would be easily
understandable and useful. Some don't like it, particularly
when a literal is used as in "i in 5". If the variant
mentioned in the response to the previous issue is implemented,
this issue is moot. If not, then one could also address this
issue by defining a __contains__ method in class int that would
always raise a TypeError. This would then make the behavior of
"i in n" identical to that of current Python.
- Might dissuade newbies from using the indexed for-loop idiom when - Might dissuade newbies from using the indexed for-loop idiom when
the standard "for item in collection:" idiom is clearly better. the standard "for item in collection:" idiom is clearly better.
Response: The standard idiom is so nice when "it fits" that it Response: The standard idiom is so nice when it fits that it
needs neither extra "carrot" nor "stick". On the other hand, needs neither extra "carrot" nor "stick". On the other hand,
one does notice cases of overuse/misuse of the standard idiom one does notice cases of overuse/misuse of the standard idiom
(due, most likely, to the awkwardness of the indexed for-loop (due, most likely, to the awkwardness of the indexed for-loop
idiom), as in: idiom), as in:
for item in sequence: for item in sequence:
print sequence.index(item) print sequence.index(item)
- Doesn't handle the general case of start,stop,step - Why not propose even bigger changes?
Response: use the existing range() or xrange() mechanisms. Or, The majority of disagreement with PEP 276 came from those who
see below. favor much larger changes to Python to address the more general
problem of specifying a sequence of integers where such
a specification is general enough to handle the starting value,
ending value, and stepping value of the sequence and also
addresses variations of open, closed, and half-open (half-closed)
integer intervals. Many suggestions of such were discussed.
These include:
Extension - adding Haskell-like notation for specifying a sequence of
integers in a literal list,
If one wants to handle general indexing (start,stop,step) without - various uses of slicing notation to specify sequences,
having to resort to using the range() or xrange() functions then
the following could be incorporated into the current proposal.
Add an "iter" method (or use some other preferred name) to - changes to the syntax of for-in loops to allow the use of
types.IntType with the following signature: relational operators in the loop header,
def iter(start=0, step=1): - creation of an integer-interval class along with methods that
overload relational operators or division operators
to provide "slicing" on integer-interval objects,
This method would have the (hopefully) obvious semantics. - and more.
Then one could do, for example: It should be noted that there was much debate but not an
overwhelming concensus for any of these larger-scale suggestions.
x = 100 Clearly, PEP 276 does not propose such a large-scale change
for i in x.iter(start=1, step=2): and instead focuses on a specific problem area. Towards the
print i end of the discussion period, several posters expressed favor
for the narrow focus and simplicity of PEP 276 vis-a-vis the more
Under this extension (for x bound to an int), ambitious suggestions that were advanced. There did appear to be
concensus for the need for a PEP for any such larger-scale,
for i in x: alternative suggestion. In light of this recognition, details of
the various alternative suggestions are not discussed here further.
would be equivalent to
for i in x.iter():
and to
for i in x.iter(start=0, step=1):
This extension is consistent with the generalization provided by
the current mechanism for dictionaries whereby one can use:
for k in d.iterkeys():
for v in d.itervalues():
for k,v in d.iteritems():
depending on one's needs, given that
for i in d:
has a meaning aimed at the most common and useful case (d.iterkeys()).
Implementation Implementation
An implementation is not available at this time and although the An implementation is not available at this time but is expected
author is not qualified to comment on such he will, nonetheless, to be straightforward. The author has implemented a subclass of
speculate that this might be straightforward and, hopefully, might int with an __iter__ method (written in Python) as a means to test
consist of little more than setting the tp_iter slot in out the ideas in this proposal, however.
types.IntType to point to a simple iterator function that would be
similar to -- or perhaps even a wrapper around -- the xrange()
function.
References References