The built-in call slice
of Python is not properly a function - like some other Python calls, it is actually a class that creates the object slice
.
The chances of you needing to use slice
directly are quite small, but there are some uses - usually more for you to check if an object is a slice
and uses it, rather than to create one directly. p>
The slice object is what is used internally by Python when using slice notation to delimit a subset of a string, such as a list or a string.
This notation is nothing more than using numbers separated by :
within a couple of brackets [ ]
used as index - as we do in:
In [70]: a = "banana"
In [71]: a[1:4]
Out[71]: 'ana'
Or
In [72]: b = list(range(10, 20))
In [73]: b
Out[73]: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
In [74]: b[:-5:2]
Out[74]: [10, 12, 14]
(In this case, the [:-5:2]
slice should be read as: take the substring from the beginning, up to 5 positions before the end, counting from 2 to 2).
As you probably know, all operations on Python objects are translated internally for calls to "magic" methods that have a predefined name - the best documentation for these methods is the language data model at this address : link
In particular, when we are going to get, assign, or delete (with the del
) a sub-string within a string, Python calls respectively the methods __getitem__
, __setitem__
and __delitem__
of the object representing the sequence.
In this process, Python transforms numbers placed in slice notation into brackets into a slice
object. That is, Python even calls the "function" slice
for us.
The object slice
is very simple, we can view the documentation or introspect it using dir
:
In [75]: a = slice(1, 4)
In [76]: dir(a)
Out[76]:
[...
'indices',
'start',
'step',
'stop']
(I deleted the magic methods of the slice because they are not important) - if you look at the "start", "step" and "stop", correspond to the attributes we passed to the beginning and end of the sequence, and "None "for step
(step), which is the third optional argument)
The indices
method requires an integer represented by the length of the sequence - and everything it does is, taking into account the length of the sequence passed as a parameter, calculates the start, end, and step indexes already taking into account the omitted parameters (that is, left blank before or after :
), negative indexes, and so on ... The values returned by the call to the indice
method can be used directly in the% function range
to generate all the indices of that slice.
It is easier to visualize with an example: let's create a subclass of list
that always returns all elements of a slice transformed into strings:
class StringSliceList(list):
def __getitem__(self, indices):
if isinstance(indices, slice):
results = []
start, stop, step = indices.indices(len(self))
for i in range(start, stop, step):
results.append(str(super().__getitem__(i)))
else:
results = super().__getitem__(indices)
return results
Ready, so we can play on the interactive terminal:
In [84]: a = StringSliceList(range(20))
In [85]: a[5:10]
Out[85]: ['5', '6', '7', '8', '9']
The slice object can be passed directly between brackets, but it will always be less readable than directly using notation with ":":
In [86]: a[slice(5,10)]
Out[86]: ['5', '6', '7', '8', '9']
I believe your maintenance as a built-in Python default is more of a slippage than anything else - it's a class that might as well be in the types
module. But as this got in the transition to Python 3, it's also very unimportant thing to break the compatibility, so it's getting.
Trivia:
In the case of a multi-dimensional index, where multiple axes are separated by ,
within brackets, such as those used in NumPy arrays, each component separated by ,
can be converted to a slice
object % separate.
class Test:
def __getitem__(self, indices):
print(indices)
Can be used:
In [89]: Test()[1:10, :, -1:5:10]
(slice(1, 10, None), slice(None, None, None), slice(-1, 5, 10))
And this does not happen if you put an extra pair of () inside [], why does this create a tuple that does not have the components converted to objects of type slice
:
In [90]: Test()[(1:10, :, -1:5:10)]
File "<ipython-input-90-32002bdbab86>", line 1
Test()[(1:10, :, -1:5:10)]
^
SyntaxError: invalid syntax