Извлечение частей списков и строк: механизм срезов в Python
Основы синтаксиса срезов
Как получить подстроку или подсписок из последовательности?
Срез позволяет извлечь часть последовательности (списка, строки, кортежа) с помощью конструкции [start:stop:step]. Все три параметра необязательны. По умолчанию start = 0, stop = длина последовательности, step = 1.
# Базовый пример со списком
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
sub = numbers[2:6]
print(sub) # [2, 3, 4, 5]Python массив срез (срез массива в python)
[2, 3, 4, 5]
Здесь start=2 (включается), stop=6 (не включается), шаг 1. Результат - новый список.
Типичная ошибка: путать stop как последний включаемый элемент. Индекс stop не включается, поэтому numbers[2:6] даёт элементы с индексами 2,3,4,5.
Различные способы использования срезов
Как извлечь элементы от начала до определённого индекса?
Если опустить start, срез начинается с первого элемента.
numbers = [0, 1, 2, 3, 4, 5]
print(numbers[:3]) # [0, 1, 2]
[0, 1, 2]
Как извлечь элементы от индекса до конца?
Опускаем stop.
numbers = [0, 1, 2, 3, 4, 5]
print(numbers[2:]) # [2, 3, 4, 5]
[2, 3, 4, 5]
Как скопировать весь список с помощью среза?
Используем [:] - копия всей последовательности.
a = [1, 2, 3]
b = a[:]
print(b) # [1, 2, 3]
print(b is a) # False
[1, 2, 3] False
Важно: это поверхностная копия. Если список содержит изменяемые объекты (например, другие списки), они будут разделяться. Для глубокого копирования используйте copy.deepcopy.
Как использовать отрицательные индексы для срезов?
Отрицательные индексы отсчитываются от конца последовательности ( -1 - последний элемент).
numbers = [0, 1, 2, 3, 4, 5]
print(numbers[-3:]) # [3, 4, 5]
print(numbers[:-2]) # [0, 1, 2, 3]
print(numbers[-4:-1]) # [2, 3, 4]
[3, 4, 5] [0, 1, 2, 3] [2, 3, 4]
Возможная путаница: numbers[:-1] даёт все элементы, кроме последнего, а numbers[-1:] - только последний. Помните: stop не включается.
Как задать шаг среза (каждые N элементов)?
Третий параметр - шаг. Например, получить каждый второй элемент.
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numbers[::2]) # [0, 2, 4, 6, 8]
print(numbers[1::2]) # [1, 3, 5, 7, 9]
[0, 2, 4, 6, 8] [1, 3, 5, 7, 9]
Как перевернуть список или строку с помощью среза?
Шаг со значением -1 обращает порядок элементов.
numbers = [0, 1, 2, 3, 4, 5]
print(numbers[::-1]) # [5, 4, 3, 2, 1, 0]
text = "Python"
print(text[::-1]) # "nohtyP"
[5, 4, 3, 2, 1, 0] nohtyP
Проблема: при step=0 возникает ошибка ValueError: slice step cannot be zero. Шаг не может быть нулевым.
Как изменить часть списка с помощью среза в присваивании?
Срезы можно использовать для замены или вставки элементов.
numbers = [0, 1, 2, 3, 4, 5]
numbers[1:4] = [10, 20, 30]
print(numbers) # [0, 10, 20, 30, 4, 5]
[0, 10, 20, 30, 4, 5]
Если правая часть короче среза, элементы удаляются; если длиннее - вставляются.
nums = [1, 2, 3, 4]
nums[1:3] = [100]
print(nums) # [1, 100, 4]
[1, 100, 4]
Ошибка: при присваивании срезу с шагом (например, numbers[::2] = [1,2]) количество элементов должно совпадать с числом заменяемых элементов, иначе ValueError: attempt to assign sequence of size ... to extended slice of size ....
Как удалить часть списка через срез?
Можно присвоить пустой список или использовать оператор del.
numbers = [0, 1, 2, 3, 4, 5]
del numbers[2:5]
print(numbers) # [0, 1, 5]
[0, 1, 5]
Как создать объект среза отдельно и применять его?
Функция slice(start, stop, step) возвращает объект среза, который можно передавать в последовательности.
numbers = [0, 1, 2, 3, 4, 5]
s = slice(1, 5, 2)
print(numbers[s]) # [1, 3]
[1, 3]
Это удобно, когда срез нужно использовать многократно.
Типичные проблемы и их решения
Пустой срез: если start >= stop при положительном шаге, результат - пустой список/строка. Ошибкой не является.
numbers = [1,2,3]
print(numbers[5:10]) # []
Выход за границы: в срезах Python допускает выход за пределы последовательности - это не вызывает ошибки, просто возвращается всё, что возможно.
numbers = [1,2,3]
print(numbers[0:100]) # [1,2,3]
Строки неизменяемы: нельзя присвоить срез строки - будет ошибка TypeError: 'str' object does not support item assignment. Можно только читать.
Расширенные примеры срезов
# 1. Срезы кортежей (работают так же, как со списками)
t = (10, 20, 30, 40, 50)
print(t[1:4]) # (20, 30, 40)
print(t[::-1]) # (50, 40, 30, 20, 10)
(20, 30, 40) (50, 40, 30, 20, 10)
# 2. Срез с изменением длины списка
items = ['a', 'b', 'c', 'd', 'e']
items[1:3] = ['x', 'y', 'z'] # вставляем 3 элемента вместо 2
print(items) # ['a', 'x', 'y', 'z', 'd', 'e']
# Если присвоить пустой список, элементы удаляются
items[1:4] = []
print(items) # ['a', 'd', 'e']
['a', 'x', 'y', 'z', 'd', 'e'] ['a', 'd', 'e']
# 3. Замена элементов с шагом (количество должно совпадать)
nums = [0, 1, 2, 3, 4, 5]
nums[::2] = [10, 20, 30] # заменяем элементы с индексами 0, 2, 4
print(nums) # [10, 1, 20, 3, 30, 5]
[10, 1, 20, 3, 30, 5]
# 4. Срез с помощью slice() для повторного использования
data = list(range(100))
s = slice(10, 51, 5)
print(data[s]) # [10, 15, 20, 25, 30, 35, 40, 45, 50]
# Применим к строке
text = "Hello, world!"
print(text[s]) # 'Hlrow' (индексы 10,15,20... но строка короче)
[10, 15, 20, 25, 30, 35, 40, 45, 50] Hlrow
# 5. Срезы вложенных списков (мелкое копирование)
matrix = [[1,2], [3,4], [5,6]]
row_copy = matrix[1] # получаем ссылку на вложенный список
row_slice = matrix[1:2] # срез создаёт новый список, содержащий ссылки на те же объекты
print(row_copy) # [3,4]
print(row_slice) # [[3,4]]
# Изменение через row_copy затронет matrix, а через row_slice - не затронет, т.к. это новый список
row_copy[0] = 99
print(matrix) # [[1,2], [99,4], [5,6]]
row_slice[0][0] = 100 # изменяет тот же вложенный список, что и matrix[1]
print(matrix) # [[1,2], [100,4], [5,6]]
[3, 4] [[3, 4]] [[1, 2], [99, 4], [5, 6]] [[1, 2], [100, 4], [5, 6]]
# 6. Срез с отрицательным шагом и границами
nums = [0, 1, 2, 3, 4, 5, 6]
print(nums[5:2:-1]) # [5,4,3] - от 5 к 2 (не включая 2)
print(nums[6:0:-2]) # [6,4,2] - чётные индексы в обратном порядке
[5, 4, 3] [6, 4, 2]
# 7. Срезы строк с учетом кодировки (Unicode)
text = "Привет, мир!"
# Строки Python - последовательность Unicode-символов, срез работает корректно
print(text[:6]) # 'Привет'
print(text[::2]) # 'Пие,и!'
Привет Пие,и!
# 8. Использование срезов для итерации с шагом
numbers = list(range(20))
for value in numbers[5:15:3]:
print(value, end=' ') # 5 8 11 14
5 8 11 14
# 9. Срез с неявными границами и отрицательным шагом
nums = [0,1,2,3,4,5]
print(nums[:3:-1]) # [5,4] - start=None (по умолчанию -1 при step<0), stop=3, идём от конца к индексу 3
print(nums[3::-1]) # [3,2,1,0] - от индекса 3 до начала
[5, 4] [3, 2, 1, 0]