From e4dbb1a74ab85d5033830ff51f873ece46725a74 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Mon, 11 Mar 2002 17:40:50 +0000 Subject: [PATCH] James's last update, and mark this PEP rejected. --- pep-0276.txt | 208 ++++++++++++++++++++++++++++----------------------- 1 file changed, 113 insertions(+), 95 deletions(-) diff --git a/pep-0276.txt b/pep-0276.txt index 984dac91c..970ddc09e 100644 --- a/pep-0276.txt +++ b/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