Если указано отрицательное значение шага, Python меняет начальное и конечное значения. Кроме того, если значения начала и конца не указаны, по умолчанию они задают начало и конец последовательности.
При условии s[i:j:k]
, следующая цитата из раздела операций с общей последовательностью из применяется документация по встроенным типам:
Если i или j опущены или отсутствуют, они становятся «конечными» значениями (конец которых зависит от знака k).
Что касается того, как это работает под капотом, в CPython есть две функции для обработки подписок на списки, list_subscript()
(для чтения) и list_ass_subscript()
(для назначения).
В обеих этих функциях, после проверки того, что нижний индекс определяет срез, выполняются вызовы PySlice_Unpack()
и PySlice_AdjustIndices()
для извлечения и нормализации начальных и конечных значений.
Обработка начальных значений
С PySlice_Unpack()
:
if (r->start == Py_None) {
*start = *step < 0 ? PY_SSIZE_T_MAX : 0;
Если начальное значение None
, а значение шага отрицательное, начальное значение установлено на максимально возможное значение .
Затем в PySlice_AdjustIndices()
:
else if (*start >= length) {
*start = (step < 0) ? length - 1 : length;
Если начальное значение больше, чем длина списка (что, несомненно, связано с назначением выше) и значение шага является отрицательным, тогда начальное значение устанавливается на length - 1
(т. е. length
относится к длине последовательности).
Остановка обработки значения
С PySlice_Unpack()
:
if (r->stop == Py_None) {
*stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
Если значение останова равно None
, а значение шага отрицательно, значение останова устанавливается на наименьшее возможное значение.
Затем в PySlice_AdjustIndices()
:
if (*stop < 0) {
*stop = (step < 0) ? -1 : 0;
Если значение остановки отрицательное (что связано с приведенным выше назначением), а значение шага отрицательное, значение остановки устанавливается до -1.
Таким образом, при вводе string[::-1]
вы получите:
- Начальное значение: len (строка) - 1
- Стоп-значение : -1
- Шаг: -1