Inspecting the slice
class in Python with dir()
, I see that it has attributes __le__
and __lt__
. Indeed I saw that the following code works:
slice(1, 2) < slice(3, 4)
# True
However, I cannot see which logic is implemented for this comparison, nor its usecase. Can anyone point me to that?
I am not asking about tuple comparison. Even if slice and tuple are compared the same way, I don't think this makes my question a duplicate. What's more, I also asked for a possible usecase of slice comparison, which the suggested duplicate does not give.
Looking at the source code for slice
reveals that the comparison is implemented by first converting the two objects into (start, stop, step)
tuples, and then comparing those tuples:
https://github.com/python/cpython/blob/6cca5c8459cc439cb050010ffa762a03859d3051/Objects/sliceobject.c#L598
As to the use cases, I am not sure of the authors' intent. I do note that there don't appear to be any comparison unit tests for anything other than equality:
https://github.com/python/cpython/blob/6f0eb93183519024cb360162bdd81b9faec97ba6/Lib/test/test_slice.py#L87
Comparing tuples : (1, 2) < (3, 4)
returns True
because (1, 2) comes before (3, 4)
.
However, (1, 2) < (0, 4)
returns False
because (1, 2) comes after (0, 4)
.
NB: <
and >
doesn't mean smaller than
or greater than
, but is before
and is after
.
So, in other words, you're comapring which is coming before and which is coming after.
Some "odd" cases (Or, misleading cases within <
and >
):
(1, 2) < (3, 4, 5)
returns True
because the missing value of the first tuple will be equal to nil
value of the operation which is zero in this case. Or you can think of it that (1, 2) come before (3, 4, 5)
.
And:
(0, 1) < (1, 0)
will returns True
because (0, 1) comes before (1, 0)
Another case:
(0, 1, 20000) < (0, 3, 1)
will returns True
because (0, 1, 20000) comes before (0, 3, 1)
.
Same logic for slice
, list
and even strings
.
For more informations, visit this answer.
Python data model only mentions that slice objects have three read-only attributes and one method. It does not mention any other properties of slices.
As mentioned by @NPE, CPython implementation indeed provides a comparison for slice objects, which simply treats slice
as a tuple of (start, end, step)
. I've checked it with a small Python program which confirmed that:
vals = []
for a in range(-5, 5):
for b in range(-5, 5):
for c in range(-5, 5):
vals.append((a, b, c))
for x in vals:
for y in vals:
assert (slice(*x) < slice(*y)) == (x < y)
However, that looks like a non-standard extension. For example, Jython also implements comparison for slices, but in a different way. Moreover, it looks like it implements comparison for all possible pairs of objects by comparing objects of the same type by their id
s, which is propagated to slices.
So, order of slices in Jython is non-deterministic. For example, the following snippet prints True True
on my system with Jython and True False
with CPython:
print(slice(1, 2) < slice(1, 3))
print(slice(1, 3) < slice(1, 2))
Summarizing: __lt__
is implemented in CPython for some obscure reason, but it's not described anywhere in documentation and other implementations may behave not only differently, but "incorrectly" (in mathematical sense). So, one should not compare slices for inequality.