# What is the point of the slice.indices method?

What is the point of the `slice.indices` method, since we have the following equality?

``````s = slice(start, stop, step)
assert range(*s.indices(length)) == range(length)[s]
``````

In the old days, `range` created a list, and `xrange` didnâ€™t always exist (and was still inferior to what `range` is now; IIRC, it couldnâ€™t be sliced like that, among other issues). Code that wanted to lazily iterate over a slice could save memory by knowing the start index, stop index and step to use for an explicit manual loop that indexed into the container. Given a `slice` object and the containerâ€™s length, those values are easily calculated, and `.indices` implements exactly that. So it converts from an abstract representation of a policy for slicing, into a concrete but still indirect representation of the actual indices that would be sliced for a given container. The `range` would represent those indices more elegantly, but the option wasnâ€™t always available in the past.

Aside from tests, documentation and the actual implementation, I only see one use of it in the Python standard library currently - in `pathlib` (comments mine):

``````# Implementation of an internal type that represents all the ancestor paths
# of a given path without storing them explicitly.
class _PathParents(Sequence):
# other methods omitted
def __getitem__(self, idx):
if isinstance(idx, slice):
# iterate over indices and recurse with integers instead of a slice
return tuple(self[i] for i in range(*idx.indices(len(self))))
# otherwise, assume we have an integer index.
# (If that's wrong, the TypeError will just propagate.)
if idx >= len(self) or idx < -len(self): # bounds check
raise IndexError(idx)
if idx < 0: # wrap negative indices
idx += len(self)
# compute the nth ancestor path from the complete path
return self._path._from_parsed_parts(self._drv, self._root,
self._tail[:-idx - 1])
``````

And, yes, that `range(*idx.indices(len(self)))` could just as easily be `range(len(self))[idx]`. There just isnâ€™t a compelling reason to change it at this point. In my own code, I freely refactor that sort of thing. Codebases shared by dozens of developers and depended on by millions of users donâ€™t have the same luxury, even with a full test suite. (I can also imagine that a lot of linters - or even human code reviewers - would see `for i in range(len` and start screaming on instinct.)

3 Likes

Thanks a lot for your detailed explanation @kknechtel, itâ€™s very clear. Do you mind copying that answer to the same question on Stack Overflow?

I eventually wrote an answer myself.

1 Like

I no longer write new answers for Stack Overflow (I will do so on Codidact going forward), but please feel free to cite/quote my post here if it can help improve the answer.

Is this something youâ€™re prepared to elaborate on, either in private or in public? I would have asked you in private but you seem to have messaging disabled.

I have been meaning to write about it on my personal blog for some time now, but havenâ€™t gotten around to it (or any other blog articles).

Okay, at least I donâ€™t have to feel bad for asking in public then Iâ€™m definitely curious, since SOâ€™s reputation isâ€¦ somewhat checkered.

Have you managed to write about it?