I understand that the slicing syntax contains 3 arguments, namely:
start
stop
step
With the following default values:
start = 0
stop = length of string
step = 1
So, for
> string = "abc"
> string[::]
will return
> "abc"
But, for
> string[::-1]
shouldn't it return:
> "a"
Since, string[start = 0] = 'a' Then, string[start + step], i.e. string[0-1] = 'c', but because its not less than stop = 3, it will break.
OR am i thinking in the wrong direction, and python simply slices the string in the usual direction and returns reverse of that string if the step is negative? To simplify, how does negative step work internally?
When a negative step value is provided, Python swaps the start and stop values. Furthermore, when no start and stop values are provided, they default to the beginning and the end of the sequence.
Given s[i:j:k]
, the following quote from the Common Sequence Operations section of the Built-in Types documentation applies:
If i or j are omitted or None, they become “end” values (which end depends on the sign of k).
In regards to how it works under the hood, in CPython there are two functions for handling list subscripts, list_subscript()
(for reading) and list_ass_subscript()
(for assigning).
In both of those functions, after verifying that the subscript specifies a slice, calls are made to PySlice_Unpack()
and PySlice_AdjustIndices()
to extract and normalize the start and stop values.
From PySlice_Unpack()
:
if (r->start == Py_None) {
*start = *step < 0 ? PY_SSIZE_T_MAX : 0;
If the start value is None
and the step value is negative, the start value is set to the largest possible value.
Then, in PySlice_AdjustIndices()
:
else if (*start >= length) {
*start = (step < 0) ? length - 1 : length;
If the start value is greater then the length of the list (which it undoubtedly is due to the assignment above) and the step value is negative, then the start value is set to length - 1
(i.e. length
refers to the length of the sequence).
From PySlice_Unpack()
:
if (r->stop == Py_None) {
*stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
If the stop value is None
and the step value is negative, the stop value is set to the smallest possible value.
Then, in PySlice_AdjustIndices()
:
if (*stop < 0) {
*stop = (step < 0) ? -1 : 0;
If the stop value is negative (which it is due to the assignment above) and the step value is negative, the stop value is set to -1.
So with an input of string[::-1]
, you end up with: