I found the documentation not quite clear, so after understanding what it actually does, I decided to share the explanation in my words:
A Slice object defines start:stop:step values, and is a way to effectively pack those 3 values into a single object (variable):
>>> s = Slice(1, 2)
>>> text[1:2] == text[s]
True
As you can see above, a slice is automatically unpacked, using colon : separators. You can't unpack it using comma , separators and need to do it manually like so:
>>> s.start, s.stop, s.step
(1, 2, None)
Perhaps default values being None is something that should be fixed (default start should be 0, default step should be 1, and you must precise the stop), but it works when slicing, also with literals:
>>> slice(1)
slice(None, 1, None)
>>> "Hello World"[slice(1)]
'H'
>>> "Hello World"[None:1:None]
'H'
However, not only you can't unpack a slice using an asterisk, but also range will not work with None:
>>> s = slice(10, 20)
>>> range(*s)
Traceback (most recent call last):
File "<blender_console>", line 1, in <module>
TypeError: range() argument after * must be an iterable, not slice
>>> range(s.start, s.stop, s.step)
Traceback (most recent call last):
File "<blender_console>", line 1, in <module>
TypeError: 'NoneType' object cannot be interpreted as an integer
You need to replace None with default values:
>>> s = slice(13)
>>> args = (s.start or 0, s.stop, 1 if s.step is None else s.step)
>>> args
(0, 13, 1)
>>> args = (s.start or 0, s.stop, s.step or 1) # step == 0 is invalid anyway
>>> args
(0, 13, 1)
>>> range(*args)
range(0, 13)
However, while slicing will automatically clamp values to a valid range, using range object and accessing an element using a single integer index, rather than a slice, can cause an IndexError:
>>> text = "Hello World"
>>> s = slice(7, 20)
>>> text[s]
'orld'
>>> for i in range(s.start, s.stop):
... print(i)
... print(text[i])
...
7
o
8
r
9
l
10
d
11
Traceback (most recent call last):
File "<blender_console>", line 3, in <module>
IndexError: string index out of range
So using slice together with range() require both manual unpacking and clamping to values in bounds. Both problems are solved with slice.indices():
>>> text = "Hello World"
>>> s = slice(7, 20)
>>> [text[i] for i in range(*s.indices(len(text)))]
['o', 'r', 'l', 'd']
slice.indices() expects an argument and doesn't accept float("inf"), so if for some reason you want to resign from clamping, you need to fall back to a previous method or use s.indices(s.stop) if stop is positive (not clamping with negative stop doesn't make sense anyway).