Когда у вас есть строка или набор чисел, рано или поздно понадобится не вся эта штука целиком, а только её часть: первая буква слова, последние три цифры номера телефона, каждый второй элемент списка. Перебирать всё руками неудобно и медленно. В Python для этого есть готовый инструмент — обращение по номеру позиции. Он работает через квадратные скобки после названия строки или списка, и один и тот же приём годится и для одного символа, и для целого куска сразу.
Этот урок открывает модуль про коллекции — наборы данных, где элементов много: строка (набор символов), список, кортеж. Прежде чем разбирать, что можно делать с коллекцией целиком, важно научиться доставать из неё нужный кусок. Это база, без которой не обойдётся почти ни одна следующая тема модуля.
Обращаемся к элементу по номеру
Представьте очередь людей, где каждый стоит на своём месте. Если вы хотите позвать конкретного человека, вы называете не имя, а его место в очереди: «третий, подойдите». Строка в Python устроена так же: каждый символ стоит на своём месте, и к нему можно обратиться по номеру этого места.
Официально это место называется индексом (index). Индекс — это номер позиции элемента внутри строки или списка, начиная с самого первого. Чтобы получить элемент по индексу, после названия переменной пишут квадратные скобки с числом внутри: word[0].
Разберём на примере строки "Python", в ней 6 символов:
word = "Python"
print(word[0]) # P
print(word[1]) # y
print(word[5]) # n
Разберём по строкам, что здесь происходит:
word = "Python"— кладём строку из 6 символов в переменнуюword.word[0]— квадратные скобки после переменной означают «возьми элемент по этому индексу». Индекс 0 — это первый символ, букваP.word[1]— индекс 1 — это второй символ, букваy. Символ под индексом 1 идёт сразу после символа под индексом 0.word[5]— в слове «Python» 6 букв, поэтому индексы идут от 0 до 5. Индекс 5 — это последний символ, букваn.
n символов, то последний доступный индекс — это n - 1, а не n. У строки из 6 символов индексы идут от 0 до 5.Считаем с конца: отрицательные индексы
Часто нужен не первый элемент, а последний — например, последняя цифра номера или последняя буква слова. Считать длину строки и вычитать единицу, чтобы найти нужный индекс, неудобно. Python решает это проще: разрешает считать не только слева направо, но и справа налево, если поставить перед числом минус.
Такой индекс называется отрицательным индексом. -1 — это последний элемент, -2 — предпоследний, и так далее в сторону начала строки.
word = "Python"
print(word[-1]) # n
print(word[-2]) # o
word[-1]— минус означает «считать с конца», число 1 после него — «первый с конца». Это букваn, последняя в слове.word[-2]— второй с конца символ, букваo.
Вырезаем кусок: срез
Индекс достаёт один-единственный символ. А что, если нужно не одно яблоко из вазы, а сразу горсть — например, первые три буквы слова или номер без кода страны? Для этого в квадратных скобках можно указать не одно число, а диапазон через двоеточие.
Такая конструкция называется срезом (slice). Общая запись выглядит так:
коллекция[start:stop]
Здесь start — индекс, с которого начинаем брать элементы (он войдёт в результат), а stop — индекс, на котором останавливаемся, причём сам этот индекс в результат не войдёт.
stop входит в результат. Срез word[1:4] берёт индексы 1, 2, 3 — но не 4. Это работает как открытая справа граница: «от 1 и до 4, не включая саму четвёрку».word = "Python"
print(word[1:4]) # yth
print(word[0:3]) # Pyt
word[1:4]— берём символы с индекса 1 по индекс 3 включительно (индекс 4 не входит): этоy,t,h, то есть"yth".word[0:3]— берём индексы 0, 1, 2 — первые три буквы слова,"Pyt".
Оба числа в срезе можно пропустить. Если пропустить start, Python возьмёт с самого начала. Если пропустить stop — возьмёт до самого конца:
word = "Python"
print(word[:3]) # Pyt -- то же самое, что word[0:3]
print(word[2:]) # thon -- с индекса 2 и до конца
print(word[:]) # Python -- вообще всё, полная копия строки
word[:3]— перед двоеточием ничего нет, значит начинаем с индекса 0. Результат тот же, что и уword[0:3].word[2:]— после двоеточия ничего нет, значит идём до самого конца строки. Получаем"thon".word[:]— пропущены оба числа, значит берём строку целиком, от начала и до конца.
Третий параметр: шаг среза
Иногда нужны не все элементы подряд, а, например, каждый второй — через один. Представьте, что вы идёте по лестнице и перешагиваете через ступеньку: считать всё равно нужно с начала, но останавливаетесь вы не на каждой ступени. У среза для этого есть третий параметр.
Он называется шагом (step) и указывается вторым двоеточием: коллекция[start:stop:step]. Шаг определяет, через сколько элементов делать следующую остановку. По умолчанию шаг равен 1 — берём каждый элемент подряд.
digits = "0123456789"
print(digits[::2]) # 02468
print(digits[1:8:2]) # 1357
digits[::2]— start и stop пустые (берём от начала и до конца), шаг 2 — каждый второй символ, начиная с индекса 0: символы 0, 2, 4, 6, 8.digits[1:8:2]— начинаем с индекса 1, останавливаемся перед индексом 8, шаг 2: символы 1, 3, 5, 7.
Если шаг сделать отрицательным, Python пойдёт не вперёд, а назад — от конца строки к началу. Это самый быстрый способ развернуть строку задом наперёд:
word = "Python"
print(word[::-1]) # nohtyP
word[::-1]— start и stop снова пустые, что при шаге -1 означает «вся строка», только двигаемся мы теперь от последнего символа к первому. Получаем строку, прочитанную задом наперёд.
[::-1] — стандартный способ развернуть строку или список. Он же используется, чтобы проверить, является ли строка палиндромом: word == word[::-1] сравнивает строку с её же перевёрнутой версией.Тот же приём работает и со списками
До сих пор все примеры были со строками, но индексы и срезы устроены совершенно одинаково для любой упорядоченной коллекции элементов. Ближайший пример — список (list): это коллекция, где вместо символов лежат любые значения — числа, строки, что угодно, и порядок между ними сохраняется. Список записывается в квадратных скобках, а значения внутри перечисляются через запятую: [10, 20, 30]. Со списками подробно разберёмся в следующих уроках, а пока используем их только как ещё один пример коллекции с номерами позиций.
scores = [55, 70, 82, 91, 68, 77]
print(scores[0]) # 55
print(scores[-1]) # 77
print(scores[1:4]) # [70, 82, 91]
print(scores[::-1]) # [77, 68, 91, 82, 70, 55]
scores[0]— первый элемент списка, число55. Индексация с нуля работает так же, как у строк.scores[-1]— последний элемент,77. Отрицательные индексы тоже работают одинаково.scores[1:4]— срез: элементы с индекса 1 по 3 включительно, индекс 4 не входит. Получаем новый список[70, 82, 91].scores[::-1]— список в обратном порядке, всё тем же приёмом, что и для строк.
Полезный трюк: копия списка через [:]
Со строками этот раздел можно пропустить — строку невозможно изменить, поэтому копировать её незачем. А вот со списком есть тонкость: если просто присвоить список другой переменной, вы получите не копию, а второе имя для того же самого списка. Изменения через одно имя будут видны и через другое — как две ручки от одной и той же двери.
Срез [:], который берёт коллекцию целиком, решает эту проблему: он не просто ссылается на тот же список, а создаёт новый, независимый, с такими же элементами.
original = [1, 2, 3]
alias = original
copy = original[:]
copy.append(99)
print(original) # [1, 2, 3]
print(copy) # [1, 2, 3, 99]
alias = original— это не копия:aliasиoriginalуказывают на один и тот же список в памяти.copy = original[:]— срез без границ создаёт новый список с теми же элементами, но отдельный от исходного.copy.append(99)— метод.append(значение)добавляет элемент в конец списка, у которого он вызван. Здесь мы вызываем его уcopy, поэтому меняется толькоcopy.- Из-за этого
print(original)покажет прежние три числа, аprint(copy)— уже четыре: добавление затронуло только независимую копию.
Частые ошибки
IndexError за пределами коллекции. Если запросить одиночный индекс, которого не существует, Python остановит программу с ошибкой:
fruits = ["яблоко", "банан", "вишня"]
print(fruits[3])
# IndexError: list index out of range
В списке fruits три элемента, значит доступны только индексы 0, 1, 2. Индекса 3 не существует, и Python сообщает об этом ошибкой вместо того, чтобы вернуть пустое значение. Это стоит воспринимать как подсказку: где-то в расчёте индекса ошибка, обычно на единицу.
fruits = ["яблоко", "банан", "вишня"]
print(fruits[1:100]) # ['банан', 'вишня']
print(fruits[10:20]) # []
fruits[1:100] просит элементы с индекса 1 до 99, но список заканчивается раньше — Python тихо останавливается на последнем реальном элементе. fruits[10:20] начинается уже за пределами списка, поэтому результат — пустой список [], а не ошибка. Разница с одиночным индексом принципиальная: индекс требует, чтобы позиция существовала, а срез — нет.
Что важно запомнить
[start:stop:step] вырезает кусок коллекции. stop в результат не входит: [:3] берёт индексы 0, 1, 2.[::-1] разворачивает строку или список задом наперёд. [:] делает независимую копию.Проверьте себя
5 вопросов
Срезы строки
PremiumСрезы списка
PremiumРазворот строки
Дана строка word. С помощью среза с шагом -1 получите строку, записанную задом наперёд, и сохраните её в переменную reversed_word.
Например, для word = "привет" должно получиться "тевирп".