[Python-ideas] Implement comparison operators for range objects

Guido van Rossum guido at python.org
Thu Oct 13 05:18:50 CEST 2011


On Wed, Oct 12, 2011 at 7:44 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On Thu, Oct 13, 2011 at 11:45 AM, Eric Snow <ericsnowcurrently at gmail.com> wrote:
>> Unless I misunderstood, Guido is basically saying the same thing (the
>> "exposing" part, that is).
>>
>> +1 on exposing start, step and end

+1

>> +1 on leaving it at that (unless it turns out to be a common case)
>
> My reading is that Guido has reserved judgment on the second part for
> now. Options are:
>
> - do nothing for 3.3 (+0 from me)
> - make sequence comparison the default (+1 from me)
> - make start/stop/step comparison the default (-1 from me)

Actually when I wrote that I was +1 on start/stop/step comparison and
-1 on sequence (really: list) comparison.

But I'd like to take a step back; we should really look at the use
cases for comparing range objects. Since they don't return lists, you
can't compare them to lists (or rather, they're always unequal).
Because of this (and because it didn't work in 3.0, 3.1, 3.2) the
proposed requirement that it should work the same as it did in Python
2 doesn't sway me.

So what's the most useful comparison for range objects? When comparing
non-empty ranges with step 1, I think we all agree. So we're left
arguing about whether all empty ranges should be equal, and about
whether non-empty ranges with step > 1 should compare equal if they
have the same start, step and length (regardless of the exact value of
stop).

But why do we compare ranges? The first message in this thread
(according to GMail) mentions unittests and suggests that it would be
handy to check if two ranges are the same, but does not give a
concrete example of such a unittest. The code example given uses
list-wise comparison, but the use case is not elaborated further. Does
anyone have an actual example of a unittest where being able to
compare ranges would have been handy? Or of any other real-life
example? Where it matter what happens if the range is empty or step is
> 1?

So, let me say I'm undecided (except on the desirability of an == test
for ranges that's more useful than identity).

FWIW, I don't think the argument from numeric comparisons carries
directly. The reason numeric comparisons (across int, float and
Decimal) ignore certain "state" of the value (like precision or type)
is that that's how we want our numbers to work.

The open question so far is: How do we want our ranges to work? My
intuition is weak, but says: range(0) != range(1, 1) != range(1, 1, 2)
and range(0, 10, 2) != range(0, 11, 2); all because the arguments
(after filling in the defaults) are different, and those arguments can
come out using the start, stop, step attributes (once we implement
them :-).

> If we do either of the latter, range.__hash__ should be updated
> accordingly (since 3.x range objects are currently hashable due to
> their reliance on the default identity comparison)

Sure. That's implied when __eq__ is updated (though a good reminder
for whoever will produce the patch).

(I'm also -1 on adding ordering comparisons; there's little
disagreement on that issue.)

PS. An (unrelated) oddity with range and Decimal:

>>> range(Decimal(10))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'Decimal' object cannot be interpreted as an integer
>>> range(int(Decimal(10)))
range(0, 10)
>>>

So int() knows something that range() doesn't. :-)

-- 
--Guido van Rossum (python.org/~guido)



More information about the Python-ideas mailing list