James's last update, and mark this PEP rejected.
This commit is contained in:
parent
73238e3409
commit
e4dbb1a74a
208
pep-0276.txt
208
pep-0276.txt
|
@ -3,7 +3,7 @@ Title: Simple Iterator for ints
|
|||
Version: $Revision$
|
||||
Last-Modified: $Date$
|
||||
Author: james_althoff@i2.com (Jim Althoff)
|
||||
Status: Draft
|
||||
Status: Rejected
|
||||
Type: Standards Track
|
||||
Created: 12-Nov-2001
|
||||
Python-Version: 2.3
|
||||
|
@ -97,13 +97,13 @@ Rationale
|
|||
indexed for-loop idiom is to use the builtin range() or xrange()
|
||||
function to generate a sequence of indices as in, for example:
|
||||
|
||||
for rowcount in range(table.getRowCount()):
|
||||
print table.getValueAt(rowcount, 0)
|
||||
for rowcount in range(table.getRowCount()):
|
||||
print table.getValueAt(rowcount, 0)
|
||||
|
||||
or
|
||||
|
||||
for rowcount in xrange(table.getRowCount()):
|
||||
print table.getValueAt(rowcount, 0)
|
||||
for rowcount in xrange(table.getRowCount()):
|
||||
print table.getValueAt(rowcount, 0)
|
||||
|
||||
From time to time there are discussions in the Python community
|
||||
about the indexed for-loop idiom. It is sometimes argued that the
|
||||
|
@ -120,7 +120,7 @@ Rationale
|
|||
|
||||
- Unwieldy, especially when combined with the len() function,
|
||||
i.e., xrange(len(sequence))
|
||||
|
||||
|
||||
- Not as convenient as equivalent mechanisms in other languages,
|
||||
|
||||
- Annoying, a "wart", etc.
|
||||
|
@ -161,8 +161,8 @@ Rationale
|
|||
would enable by default the following shortcut for the indexed
|
||||
for-loop idiom:
|
||||
|
||||
for rowcount in table.getRowCount():
|
||||
print table.getValueAt(rowcount, 0)
|
||||
for rowcount in table.getRowCount():
|
||||
print table.getValueAt(rowcount, 0)
|
||||
|
||||
The following benefits for this approach vis-a-vis the current
|
||||
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:
|
||||
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
|
||||
|
||||
|
@ -210,8 +206,8 @@ Backwards Compatibility
|
|||
1) The common case where one forgets to include range() or
|
||||
xrange(), for example:
|
||||
|
||||
for rowcount in table.getRowCount():
|
||||
print table.getValueAt(rowcount, 0)
|
||||
for rowcount in table.getRowCount():
|
||||
print table.getValueAt(rowcount, 0)
|
||||
|
||||
in Python 2.2 raises a TypeError exception.
|
||||
|
||||
|
@ -238,11 +234,32 @@ Backwards Compatibility
|
|||
relatively easy to correct should it happen.
|
||||
|
||||
|
||||
|
||||
Issues:
|
||||
|
||||
Based on some preliminary discussion on the Python interest
|
||||
mailing list, the following concerns have been voiced:
|
||||
Extensive discussions concerning PEP 276 on the Python interest
|
||||
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?
|
||||
|
||||
|
@ -250,17 +267,12 @@ Issues:
|
|||
convention for indexing sequences starting at 0 and stopping at
|
||||
(inclusively) the index whose value is one less than the length
|
||||
of the sequence, it is argued that the proposed sequence is
|
||||
reasonably intuitive to a Python programmer while being useful
|
||||
and practical.
|
||||
|
||||
- "in" (as in "for i in x") does not match standard English usage
|
||||
in this case. "up to" or something similar might be better.
|
||||
|
||||
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.
|
||||
reasonably intuitive to the Python programmer while being useful
|
||||
and practical. More importantly, it is argued that once learned
|
||||
this convention is very easy to remember. Note that the doc
|
||||
string for the range function makes a reference to the
|
||||
natural and useful association between range(n) and the indices
|
||||
for a list whose length is n.
|
||||
|
||||
- Possible ambiguity
|
||||
|
||||
|
@ -268,104 +280,110 @@ Issues:
|
|||
|
||||
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
|
||||
several of the posters.
|
||||
Response: This is exactly the same situation with strings in
|
||||
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
|
||||
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.
|
||||
to
|
||||
|
||||
- It would be better to reuse the slicing literal syntax attached
|
||||
to the int class, e.g., int[0:10]
|
||||
for i in xrange(n):
|
||||
|
||||
Response: Same as previous response. In addition, design
|
||||
consideration needs to be given to what it would mean if one
|
||||
uses slicing syntax after some arbitrary class other than class
|
||||
int. Needs a PEP.
|
||||
This approach gives the same results in a for-loop as an
|
||||
__iter__ method would but would prevent iteration on integer
|
||||
values in any other context. Lists and tuples, for example,
|
||||
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
|
||||
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,
|
||||
one does notice cases of overuse/misuse of the standard idiom
|
||||
(due, most likely, to the awkwardness of the indexed for-loop
|
||||
idiom), as in:
|
||||
|
||||
for item in sequence:
|
||||
print sequence.index(item)
|
||||
for item in sequence:
|
||||
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,
|
||||
see below.
|
||||
The majority of disagreement with PEP 276 came from those who
|
||||
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
|
||||
having to resort to using the range() or xrange() functions then
|
||||
the following could be incorporated into the current proposal.
|
||||
- various uses of slicing notation to specify sequences,
|
||||
|
||||
Add an "iter" method (or use some other preferred name) to
|
||||
types.IntType with the following signature:
|
||||
- changes to the syntax of for-in loops to allow the use of
|
||||
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
|
||||
for i in x.iter(start=1, step=2):
|
||||
print i
|
||||
|
||||
Under this extension (for x bound to an int),
|
||||
|
||||
for i in x:
|
||||
|
||||
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()).
|
||||
Clearly, PEP 276 does not propose such a large-scale change
|
||||
and instead focuses on a specific problem area. Towards the
|
||||
end of the discussion period, several posters expressed favor
|
||||
for the narrow focus and simplicity of PEP 276 vis-a-vis the more
|
||||
ambitious suggestions that were advanced. There did appear to be
|
||||
concensus for the need for a PEP for any such larger-scale,
|
||||
alternative suggestion. In light of this recognition, details of
|
||||
the various alternative suggestions are not discussed here further.
|
||||
|
||||
|
||||
Implementation
|
||||
|
||||
An implementation is not available at this time and although the
|
||||
author is not qualified to comment on such he will, nonetheless,
|
||||
speculate that this might be straightforward and, hopefully, might
|
||||
consist of little more than setting the tp_iter slot in
|
||||
types.IntType to point to a simple iterator function that would be
|
||||
similar to -- or perhaps even a wrapper around -- the xrange()
|
||||
function.
|
||||
An implementation is not available at this time but is expected
|
||||
to be straightforward. The author has implemented a subclass of
|
||||
int with an __iter__ method (written in Python) as a means to test
|
||||
out the ideas in this proposal, however.
|
||||
|
||||
|
||||
References
|
||||
|
|
Loading…
Reference in New Issue