This is exactly the purpose of the indices
method of the slice
class.
As explained in the built-in help:
Help on built-in function indices:
indices(...) method of builtins.slice instance
S.indices(len) -> (start, stop, stride)
Assuming a sequence of length len, calculate the start and stop
indices, and the stride length of the extended slice described by
S. Out of bounds indices are clipped in a manner consistent with the
handling of normal slices.
Thus, pass it the length of the sequence that will be sliced, in order to get the corresponding start/stop/stride values:
>>> s = slice(-2, None, None)
>>>
>>> things = ['a', 'b', 'c', 'd', 'e', 'f']
>>> things[s]
['e', 'f']
>>> s.indices(len(things))
(4, 6, 1)
>>> x, y, z = s.indices(len(things))
>>> things[x:y:z]
['e', 'f']
Which can of course be used to construct the corresponding range
of values:
>>> list(range(*s.indices(len(things))))
[4, 5]
As an aside, range
objects can be indexed and sliced directly, and converting them to lists is as easy as passing them directly to the list
type. Thus:
>>> list(range(len(things))[s])
[4, 5]
>>> list(range(len(things)))[s]
[4, 5]
This is simpler for getting an actual list of indices; in other contexts (for example, implementing __getitem__
for a custom type) the start/stop/stride values may be more directly useful.