Movatterモバイル変換


[0]ホーム

URL:


Following system colour schemeSelected dark colour schemeSelected light colour scheme

Python Enhancement Proposals

PEP 284 – Integer for-loops

Author:
David Eppstein <eppstein at ics.uci.edu>,Gregory Ewing <greg.ewing at canterbury.ac.nz>
Status:
Rejected
Type:
Standards Track
Created:
01-Mar-2002
Python-Version:
2.3
Post-History:


Table of Contents

Abstract

This PEP proposes to simplify iteration over intervals ofintegers, by extending the range of expressions allowed after a“for” keyword to allow three-way comparisons such as

forlower<=var<upper:

in place of the current

foriteminlist:

syntax. The resulting loop or list iteration will loop over allvalues of var that make the comparison true, starting from theleft endpoint of the given interval.

Pronouncement

This PEP is rejected. There were a number of fixable issues withthe proposal (see the fixups listed in Raymond Hettinger’spython-dev post on 18 June 2005[1]). However, even with the fixups theproposal did not garner support. Specifically, Guido did not buythe premise that therange() format needed fixing, “The whole point(15 years ago) ofrange() was toavoid needing syntax to specify aloop over numbers. I think it’s worked out well and there’s nothingthat needs to be fixed (exceptrange() needs to become an iterator,which it will in Python 3.0).”

Rationale

One of the most common uses of for-loops in Python is to iterateover an interval of integers. Python provides functionsrange()andxrange() to generate lists and iterators for such intervals,which work best for the most frequent case: half-open intervalsincreasing from zero. However, therange() syntax is more awkwardfor open or closed intervals, and lacks symmetry when reversingthe order of iteration. In addition, the call to an unfamiliarfunction makes it difficult for newcomers to Python to understandcode that usesrange() orxrange().

The perceived lack of a natural, intuitive integer iterationsyntax has led to heated debate on python-list, and spawned atleast four PEPs before this one.PEP 204 (rejected) proposedto re-use Python’s slice syntax for integer ranges, leading to aterser syntax but not solving the readability problem ofmulti-argumentrange().PEP 212 (deferred) proposed severalsyntaxes for directly converting a list to a sequence of integerindices, in place of the current idiom

range(len(list))

for such conversion, andPEP 281 proposes to simplify the sameidiom by allowing it to be written as

range(list).

PEP 276 proposes to allow automatic conversion of integers toiterators, simplifying the most common half-open case but notaddressing the complexities of other types of interval.Additional alternatives have been discussed on python-list.

The solution described here is to allow a three-way comparisonafter a “for” keyword, both in the context of a for-loop and of alist comprehension:

forlower<=var<upper:

This would cause iteration over an interval of consecutiveintegers, beginning at the left bound in the comparison and endingat the right bound. The exact comparison operations used woulddetermine whether the interval is open or closed at either end andwhether the integers are considered in ascending or descendingorder.

This syntax closely matches standard mathematical notation, so islikely to be more familiar to Python novices than the currentrange() syntax. Open and closed interval endpoints are equallyeasy to express, and the reversal of an integer interval can beformed simply by swapping the two endpoints and reversing thecomparisons. In addition, the semantics of such a loop wouldclosely resemble one way of interpreting the existing Pythonfor-loops:

foriteminlist

iterates over exactly those values of item that cause theexpression

iteminlist

to be true. Similarly, the new format

forlower<=var<upper:

would iterate over exactly those integer values of var that causethe expression

lower<=var<upper

to be true.

Specification

We propose to extend the syntax of a for statement, currently

for_stmt:"for"target_list"in"expression_list":"suite["else"":"suite]

as described below:

for_stmt:"for"for_test":"suite["else"":"suite]for_test:target_list"in"expression_list|or_exprless_compor_exprless_compor_expr|or_exprgreater_compor_exprgreater_compor_exprless_comp:"<"|"<="greater_comp:">"|">="

Similarly, we propose to extend the syntax of list comprehensions,currently

list_for:"for"expression_list"in"testlist[list_iter]

by replacing it with:

list_for:"for"for_test[list_iter]

In all cases the expression formed by for_test would be subject tothe same precedence rules as comparisons in expressions. The twocomp_operators in a for_test must be required to be both ofsimilar types, unlike chained comparisons in expressions which donot have such a restriction.

We refer to the two or_expr’s occurring on the left and rightsides of the for-loop syntax as the bounds of the loop, and themiddle or_expr as the variable of the loop. When a for-loop usingthe new syntax is executed, the expressions for both bounds willbe evaluated, and an iterator object created that iterates throughall integers between the two bounds according to the comparisonoperations used. The iterator will begin with an integer equal ornear to the left bound, and then step through the remainingintegers with a step size of +1 or -1 if the comparison operationis in the set described by less_comp or greater_comp respectively.The execution will then proceed as if the expression had been

forvariableiniterator

where “variable” refers to the variable of the loop and “iterator”refers to the iterator created for the given integer interval.

The values taken by the loop variable in an integer for-loop maybe either plain integers or long integers, according to themagnitude of the bounds. Both bounds of an integer for-loop mustevaluate to a real numeric type (integer, long, or float). Anyother value will cause the for-loop statement to raise aTypeErrorexception.

Issues

The following issues were raised in discussion of this and relatedproposals on the Python list.

  • Should the right bound be evaluated once, or every time throughthe loop? Clearly, it only makes sense to evaluate the leftbound once. For reasons of consistency and efficiency, we havechosen the same convention for the right bound.
  • Although the new syntax considerably simplifies integerfor-loops, list comprehensions using the new syntax are not assimple. We feel that this is appropriate since for-loops aremore frequent than comprehensions.
  • The proposal does not allow access to integer iterator objectssuch as would be created byxrange. True, but we see this as ashortcoming in the general list-comprehension syntax, beyond thescope of this proposal. In addition,xrange() will still beavailable.
  • The proposal does not allow increments other than 1 and -1.More general arithmetic progressions would need to be created byrange() orxrange(), or by a list comprehension syntax such as
    [2*xfor0<=x<=100]
  • The position of the loop variable in the middle of a three-waycomparison is not as apparent as the variable in the present
    foriteminlist

    syntax, leading to a possible loss of readability. We feel thatthis loss is outweighed by the increase in readability from anatural integer iteration syntax.

  • To some extent, this PEP addresses the same issues asPEP 276.We feel that the two PEPs are not in conflict sincePEP 276is primarily concerned with half-open ranges starting in 0(the easy case ofrange()) while this PEP is primarily concernedwith simplifying all other cases. However, if this PEP isapproved, its new simpler syntax for integer loops could to someextent reduce the motivation forPEP 276.
  • It is not clear whether it makes sense to allow floating pointbounds for an integer loop: if a float represents an inexactvalue, how can it be used to determine an exact sequence ofintegers? On the other hand, disallowing float bounds wouldmake it difficult to usefloor() andceiling() in integerfor-loops, as it is difficult to use them now withrange(). Wehave erred on the side of flexibility, but this may lead to someimplementation difficulties in determining the smallest andlargest integer values that would cause a given comparison to betrue.
  • Should types other than int, long, and float be allowed asbounds? Another choice would be to convert all bounds tointegers byint(), and allow as bounds anything that can be soconverted instead of just floats. However, this would changethe semantics:0.3<=x is not the same asint(0.3)<=x, and itwould be confusing for a loop with 0.3 as lower bound to startat zero. Also, in generalint(f) can be very far fromf.

Implementation

An implementation is not available at this time. Implementationis not expected to pose any great difficulties: the new syntaxcould, if necessary, be recognized by parsing a general expressionafter each “for” keyword and testing whether the top leveloperation of the expression is “in” or a three-way comparison.The Python compiler would convert any instance of the new syntaxinto a loop over the items in a special iterator object.

References

[1]
Raymond Hettinger, Propose updating PEP 284 – Integer for-loopshttps://mail.python.org/pipermail/python-dev/2005-June/054316.html

Copyright

This document has been placed in the public domain.


Source:https://github.com/python/peps/blob/main/peps/pep-0284.rst

Last modified:2025-02-01 08:55:40 GMT


[8]ページ先頭

©2009-2025 Movatter.jp