Срезы в Python

В этой статье вы углубите знания о срезах в Python и узнаете, как использовать их для извлечения данных из последовательности и присвоения им данных.

Скорее всего, вы уже знакомы со срезами. В предыдущих статьях мы касались слайсинга списков.

Технически слайсинг опирается на индексирование. Поэтому срезы работают только с типами последовательностей.

Для изменяемых типов последовательностей, таких как списки, можно использовать срезы для извлечения и присвоения данных. Например:

colors = ['красный', 'зеленый', 'синий', 'оранжевый']

# извлекаем данные
print(colors[1:3])

# присваиваем новые значения
colors[1:3] = ['розовый', 'черный']
print(colors)

Вывод

['зеленый', 'синий']
['красный', 'розовый', 'черный', 'оранжевый']

Однако срезы можно использовать для извлечения данных и из неизменяемых последовательностей. Например:

topic = 'Срезы в Python'

# извлекаем данные
print(topic[0:6])

Вывод

Срезы

Если вы попытаетесь использовать срезы для присвоения данных неизменяемой последовательности, Python сообщит об ошибке. Например:

topic[0:6] = 'Списки' # ошибка TypeError: 'str' object does not support item assignment

Срез последовательность[начало:конец] возвращает элементы с индекса начало до индекса конец - 1.

Совет. Представляйте что индексы находятся между элементами, когда вы делаете срез последовательности — как показано на рисунке ниже.

Срез — это объект

В Python все является объектом, в том числе — срезы.

Когда вы используете синтаксис срезов:

последовательность[начало:конец]

... на самом деле начало:конец — объект класса slice.

slice(начало, конец)

Давайте убедимся в этом с помощью функции type():

s = slice(1, 3)

print(type(s))
print(s.start, s.stop)

Вывод

<class 'slice'>
1 3

Тот факт, что срезы являются объектом типа slice, позволяет не использовать классический синтаксис срезов

colors[1:3]

... а, например, использовать срез как объект: 

colors = ['красный', 'зеленый', 'синий', 'оранжевый']
s = slice(1, 3)

print(colors[s])

Вывод

['зеленый', 'синий']

Границы срезов

Срез последовательность[начало:конец] выбирает элементы, чей индекс находится в промежутке между с индексами начало и конец (не включая элемент с индексом конец).

Другими словами, он возвращает все элементы последовательности по индексу n, где n удовлетворяет следующему выражению:

начало <= n <= конец

Если начало или конец больше, чем длина последовательности, Python использует len(последовательность) вместо начало или конец соответсвенно.

Например, если указать конец больше длины списка, все равно выведутся все элементы. Python использует в качестве верхней границы len(последовательность).

colors = ['красный', 'зеленый', 'синий', 'оранжевый']
print(colors[0:100])

Вывод

['красный', 'зеленый', 'синий', 'оранжевый']

Обе границы начало и конец опциональные. Если их не указывать, будут использованы зачения по умолчанию: начало — 0, конец — len(последовательность).

colors = ['красный', 'зеленый', 'синий', 'оранжевый']
print(colors[10:])

Вывод

['красный', 'зеленый', 'синий', 'оранжевый']

Не указали верхнюю границы — все равно вывелся весь списка.

Отрицательные границы срезов

Объект slice также принимает отрицательные начальные и конечные границы.

В следующем примере для слайсинга списка используются отрицательные начальные и конечные границы:

colors = ['красный', 'зеленый', 'синий', 'оранжевый']

print(colors[-4:-2])

Вывод

['красный', 'зеленый']

Чтобы получить элементы 'синий' и 'оранжевый' из списка colors, можно объединить отрицательные и положительные границы:

colors = ['красный', 'зеленый', 'синий', 'оранжевый']
print(colors[-2:4])

Вывод

['синий', 'оранжевый']

Шаг в срезах

Срезы поддерживают третий аргумент — шаг. Если его не указывать, по умолчанию значение шага равно 1.

последовательность[начало:конец:шаг] 

Если вспомнить, что срезы являются объектом, срезы с шагом можно использовать и так:

s = slice(начало, конец, шаг) 
последовательность[s]

Пример

colors = ['красный', 'зеленый', 'синий', 'оранжевый']
print(colors[0:4:2])

Вывод

['красный', 'синий']

Метод indices()

Объект slice по сути определяет последовательность индексов для выбора элементов последовательности.

Чтобы сделать выбор элементов более удобным, у класса slice есть метод indices(), который возвращает эквивалентный диапазон (начало, конец, шаг) для любого среза последовательности с заданной длиной:

slice(начало, конец, шаг).indices(длина) # вернется кортеж (i, j, k)

Вы можете использовать значения кортежа, который возвращает indices() для создания списка индексов с помощью функции range(). Например:

colors = ['красный', 'зеленый', 'синий', 'оранжевый']

s = slice(0, 4, 2)
t = s.indices(len(colors))

for index in range(*t):
    print(colors[index])

Вывод

красный
синий

Как это работает

  1. Создается объект slice со следующими параметрами: начало — 0, конец — 4, шаг — 2.
  2. Возвращается кортеж индексов среза последовательности, длина которого равна длине списка colors.
  3. Кортеж передается в функцию range() для выбора элементов из списка colors.

Что нужно запомнить

  • Срезы работают только для последовательностей: изменяемых и неизменяемых.
  • Срез — это объект класса slice.
codechick

СodeСhick.io - простой и эффективный способ изучения программирования.

2024 ©