Шаблон среза, который можно применить к последовательности.
Синтаксис:
slice(stop)
slice(start, stop)
slice(start, stop, step)
Параметры:
start
- тип int
, начальный индекс среза;stop
- тип int
, конечный индекс среза (не будет входить в конечный результат);step
- тип int
, шаг, с которым нужно выбирать элементы.
Возвращаемое значение:
Описание:
Иногда требуется получить из последовательности не один элемент, а сразу несколько или элементы по некоторой закономерности. Для этого существуют срезы. Надо отметить, что изначальная последовательность никак не меняется, объект slice()
создает копию.
Класс
slice()
вернет объект, представляющий срез/часть
последовательности, которая будет следовать шаблону, указанному в аргументах. Возвращаемый объект среза представляет новый набор индексов начальной последовательности, заданных диапазоном
start
,
stop
,
step
, как в
range()
.
sequence[slice(x, y, z)]
# эквивалентно вызову
sequence[x, y, z]
Срезы удобнее создать при помощи расширенного синтаксиса индексации, квадратных скобок []
с двоеточиями в качестве разделителей внутри. Например: x[start:stop:step]
или x[start:stop]
x[a:b]
срез от a
до b-1
элементов x[a], x[a+1], …, x[b-1]
.x[a:b:-1]
срез от b
до a+1
элементов x[b], x[b-1], …, x[a+1]
, то есть меняется порядок элементов.x[a:b:k]
срез с шагом k
: x[a], x[a+k], x[a+2*k],…
. Если значение k < 0
, то элементы идут в противоположном порядке.- Каждое из чисел
a
или b
может отсутствовать, что означает “начало последовательности” или “конец последовательности”
Особенности среза:
- Отрицательные значения старта и стопа означают, что считать надо не с начала, а с конца коллекции.
- Отрицательное значение шага - перебор ведём в обратном порядке справа налево.
- Если не указан старт
[:stop:step]
- начинаем с самого края коллекции, то есть с первого элемента (включая его), если шаг положительный или с последнего (включая его), если шаг отрицательный (и соответственно перебор идет от конца к началу). - Если не указан стоп
[start:: step]
- идем до самого края коллекции, то есть до последнего элемента (включая его), если шаг положительный или до первого элемента (включая его), если шаг отрицательный (и соответственно перебор идет от конца к началу). step = 1
, то есть последовательный перебор слева направо указывать не обязательно - это значение шага по умолчанию. В таком случае достаточно указать [start:stop]
Можно сделать даже так [:]
- это значит взять коллекцию целиком
Важно: При срезе, первый индекс входит в выборку, а второй нет!
То есть от start
включительно, до stop
, где stop
не включается в результат. Поэтому, например, sequence[::-1]
не идентично sequence[:0:-1]
, так как в первом случае мы включим все элементы, а во втором дойдем до индекса sequence[0]
, но не включим его!
Метод среза slice.indices()
.
Каждый объект slice()
в Python имеет метод .indices
. Этот метод возвращает кортеж (start, end, step)
, с помощью которой можно построить цикл, эквивалентный операции среза. Звучит сложно? Разбираемся:
>>> sequence = list("Python")
Затем создадим объект slice()
. Например возьмем каждый второй элемент, т.е. sequence[::2]
.
# эквивалентно `[::2]`
>>> my_slice = slice(None, None, 2)
Так как в качестве некоторых аргументов используется None
, то объект slice()
должен вычислять фактические значения индекса на основе длины последовательности. Следовательно, чтобы получить кортеж фактических индексов (без None
), необходимо передать длину последовательности методу slice.indices()
, например:
>>> indices = my_slice.indices(len(sequence))
>>> indices
# (0, 6, 2)
Теперь можно воссоздать цикл следующим образом:
sequence = list("Python")
start, stop, step = (0, 6, 2)
i = start
while i != stop:
print(sequence[i])
i = i+step
Больше примеров:
Примеры получения срезов при помощи объекта slice()
.
>>> line = 'срезы'
>>> y = slice(0, 3)
>>> line[y]
# сре
# что эквивалентно использованию
# расширенного синтаксиса индексации
>>> line[0:3]
# сре
##############
# Еще примеры
##############
>>> lst = list(range(10))
>>> lst
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> i = slice(2,5,2)
>>> lst[i]
# [2, 4]
>>> i = slice(2)
>>> lst[i]
# [0, 1]
>>> i = slice(2, 3)
>>> lst[i]
# [2]
>>> i = slice(-3)
>>> lst[i]
# [0, 1, 2, 3, 4, 5, 6]
>>> i = slice(None, 5, -1)
>>> lst[i]
# [9, 8, 7, 6]
>>> i = slice(-2,5,-1)
>>> lst[i]
# [8, 7, 6]
>>> i = slice(0, None, 2)
>>> lst[i]
# [0, 2, 4, 6, 8]
>>> i = slice(-1, None, -2)
>>> lst[i]
# [9, 7, 5, 3, 1]
>>> i = slice(None, None, -1)
>>> lst[i]
# [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
С помощью объекта среза
slice()
или расширенного синтаксиса индексации можно создавать копии
списков, для последующего изменения, не боясь, что изменится оригинал.
>>> x = [0, 1, 2, 3]
>>> y = x[::]
>>> y[0] = 10
>>> x, y
# [0, 1, 2, 3], [10, 1, 2, 3]
Можно развернуть список или строку, только это будет копия оригинала.
>>> x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> y = x[::-1]
>>> x, y
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> x = 'кукарача'
>>> y = x[::-1]
>>> print(x, y, sep=' <---> ')
# кукарача <---> ачаракук
Срезом, так же можно изменить список, но не
строку или
кортеж, т. к. они неизменяемы.
>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x[3:7] = [0, 0, 0, 0]
>>> x
# [1, 2, 3, 0, 0, 0, 0, 8, 9, 10]