[Tutor] Looping

Paul McGuire ptmcg at austin.rr.com
Tue Apr 21 00:56:59 CEST 2009


> 
> xrange was a kludge to improve on range's memory efficiency
> but it is a horrible name that obscures the code.
> 
> Also it does not exist in v3 so if you use it you will need to change
> the code for v3. It is as well to be as consistent with v3 as possible
> IMHO
> 
> Alan G

I have felt this way also (i.e., "xrange was a kludge" and "it is a horrible
name"), and have resisted the general adoption of xrange in my code.
Fortunately, I rarely use range, but iterate over sequences directly; or if
I absolutely need the item's index, I iterate over enumerate(seq).

But even if you use "range" exclusively, you may need to change code when
migrating to Python 3.  In Py2, range returns a list; in Py3 range returns
an iterator (a la Py2-xrange's behavior).  If you have code that uses the
value returned from range as a list, then in Py3 you will need to explicitly
convert it to a list using "list(range(n))".

I concur with Alan's suggestion that you code to Py3 semantics, but there
are certainly cases where xrange makes sense vs. range (such as doing some
sort of repetitive test 1e8 times, there is no sense in creating a
100-million entry list just to iterate over it).  So I'll propose some
usages for those who use range:

1. For Py2-Py3 range-xrange compatibility, add this code to the top of your
Python scripts:

try:
    range = xrange
except NameError:
    pass

In this way, your code under Py2 will use xrange whenever you call range,
and you will adopt the future-compatible range behavior.  (Hmm, maybe this
would have been a good option to add to the "future" module...)

2. In all cases where you really must use the result returned from range as
a list, ALWAYS write this as "list(range(n))", as in:

nonnegative_numbers_up_to_but_not_including_10 = list(range(10))
even_numbers_up_to_but_not_including_20 = list(range(0,20,2))

Using the "list(range(n))" form when you actually need a list will prepare
you for the change in idiom when you upgrade to Py3, and is fully Py2
compatible (even if you don't first bind xrange to range as in suggestion 1
- it simply copies the original list).  It also makes it very explicit that
you REALLY WANT THE RANGE AS A LIST, and not just as something for counting
up to n.

-- Paul




More information about the Tutor mailing list