К содержанию

Модуль 4 · Урок 4.1

Строки

Индексы и срезы, неизменяемость, методы строк и подсчёт фрагментов с перекрытием.

8 задач

Программы постоянно работают с текстом: имя, слово, запись числа, строка из файла. В задачах ЕГЭ часто нужно найти в длинной строке символ, кусок или повтор. Python берёт из строки символ по номеру, кусок по срезу и строит из старой строки новую. Срезы устроены как range из прошлого урока: начало включено, граница нет.

Индексы и срезы покажем на строках "PYTHON" и "ABCDEFG", а потом соберём новую строку из символов старой.

Длина и индексы

У строки есть длина и элементы, пронумерованные с нуля. Порядок символов важен: "кот" и "ток" состоят из одинаковых букв, но являются разными строками.

word = "PYTHON"print(len(word))print(word[0])print(word[2])print(word[-1])
6 P T N

len получает количество элементов. Индекс — номер позиции. Положительные индексы начинаются с 0: это удобно понимать как число шагов от начала. Для строки длины n допустимы индексы от 0 до n - 1. Отрицательные индексы считают с конца: −1 — последний элемент, −2 — предпоследний.

Над буквой — индекс от начала, под ней — с конца. У последней буквы N индексы 5 и −1.

Обращение к word[6] вызывает ошибку: такой позиции нет.

word = "PYTHON"print(word[6])
IndexError: string index out of range

У пустой строки "" длина 0, поэтому в ней нет даже элемента с индексом 0. Отдельного встроенного типа «символ» в Python нет: word[0] тоже строка, просто длины 1.

Срезы

Срез берёт элементы от начала до остановки, не включая её. Срез получает последовательность элементов по правилу s[start:stop:step]. Остановка не включается, как в range.

s = "ABCDEFG"print(s[1:4])print(s[:3])print(s[4:])print(s[::2])print(s[::-1])print(s[5:1:-1])
BCD ABC EFG ACEG GFEDCBA FEDC
Границы среза стоят между символами: start = 1 перед B, stop = 4 перед E. Поэтому E в срез не входит, а длина среза 4 − 1 = 3.

s[1:4] берёт индексы 1, 2, 3 — ровно как range(1, 4). Для положительного шага пропущенное начало означает начало строки, пропущенная остановка — её конец. Для отрицательного шага значения по умолчанию меняются: движение начинается с конца и идёт до начала. Поэтому s[::-1] разворачивает всю строку, а s[5:1:-1] идёт от индекса 5 вниз до 2.

При шаге −1 срез идёт справа налево: от индекса 5 к индексу 2; F берётся первой, C — последней, индекс 1 уже не входит.
Тонкости:пропущенная граница и −1

Пропущенная граница и явно написанное -1 — не одно и то же. В s[5:-1:-1] явное -1 означает последний индекс, то есть 6: движение от 5 назад к 6 не даёт ни одного символа, срез пуст. Пропущенная граница при отрицательном шаге означает «до самого начала».

Срез за пределами длины обрезается: s[:100] вернёт всю строку. Одиночный неверный индекс вызывает ошибку. Срез может быть пустым; это нормальный результат. Шаг 0 недопустим.

Проверь срезы сам. Песочница начинается с s[::2] — каждый второй символ. Поле start или stop можно оставить пустым, шаг — сделать отрицательным. Номер под буквой — очередь, в которой срез её берёт.

s[::2] → 'ACEG'

Неизменяемость

Строку нельзя изменить на месте — можно только построить новую. Неизменяемость означает, что нельзя заменить элемент внутри существующей строки:

s = "кот"s[0] = "р"
TypeError: 'str' object does not support item assignment

Можно построить новую строку и связать с ней имя:

s = "кот"s = "р" + s[1:]print(s)
рот

+ соединяет строки. Это действие называют конкатенацией. "ab" * 3 повторяет текст и создаёт "ababab". Старая строка при этом не меняется: имя просто связывается с новой.

Перебор и сборка строки

Новую строку собирают по символам: перебирают старую и добавляют нужные символы к накопителю. Строку нельзя изменить, но можно построить новую. Уберём из слова все буквы «а» — пройди программу по шагам и следи за result:

word = "банан"result = ""for ch in word:    if ch != "а":        result += chprint(result)
бнн

for ch in word берёт символы по одному, как в уроке о for. Накопитель-строка начинается с пустой строки "" — как сумма с 0, а result += ch дописывает символ в конец.

Когда нужны соседние символы, перебирают индексы. Посчитаем пары одинаковых соседних букв — такие задачи встречаются в ЕГЭ:

s = "AABBBC"count = 0for i in range(len(s) - 1):    if s[i] == s[i + 1]:        count += 1print(count)
3

У последнего символа соседа справа нет, поэтому индекс i идёт до len(s) - 2 включительно — это range(len(s) - 1). Пары AA, BB и ещё одна BB дают 3.

Методы строк

Метод — действие, которое вызывают у объекта через точку. Запись s.lower() означает «вызвать действие lower для строки s». Точка связывает действие с объектом, скобки запускают его.

Частые методы строки на примере s = "Banana" — выбери метод, чтобы увидеть результат:

lower / upper
s.lower() → 'banana'новая строка в нижнем регистре; s.upper() — в верхнем
strip
" Banana ".strip() → 'Banana'пробелы и переводы строки по краям; rstrip — только справа
replace
s.replace("a", "o") → 'Bonono'все вхождения; с третьим аргументом 1 — только первое
find
s.find("an") → 1индекс первого вхождения, −1 если нет
count
s.count("an") → 2неперекрывающиеся вхождения
startswith
s.startswith("Ba") → Trueendswith — проверка конца
zfill
"101".zfill(8) → '00000101'нули слева до длины 8
in
"nan" in s → Trueесть ли фрагмент внутри строки

Методы не меняют исходную строку. Вызов s.replace("a", "b") с проигнорированным результатом не обновляет s; для этого нужно присваивание.

s = "  Python  "clean = s.strip().lower()print(clean)print("th" in clean, clean.find("th"))print("101".zfill(8))
python True 2 00000101

Сначала strip создаёт промежуточную строку без крайних пробелов; затем lower вызывается уже для неё. Это два последовательных действия. zfill удобен, когда запись числа нужно выровнять по длине, например двоичную запись до восьми знаков.

Не проверяй поиск как if s.find(part):: индекс 0 ложен, а отсутствие с индексом −1 истинно. Используй part in s или явное сравнение с −1.

Тонкости:что именно убирает strip

strip("ab") убирает по краям любой набор символов a и b, а не обязательно целую подстроку "ab". Для удаления ровно одного известного префикса существует removeprefix.

count без перекрытий

count не считает перекрывающиеся вхождения. В "AAAA" фрагмент "AA" начинается на позициях 0, 1 и 2. Но "AAAA".count("AA") возвращает 2: после найденного совпадения поиск продолжится за ним.

«AA» начинается в «AAAA» с позиций 0, 1 и 2. count находит начала 0 и 2, а начало 1 пропускает: оно перекрывается с найденным.

Для подсчёта всех начал можно проверить каждую позицию:

s = "AAAA"part = "AA"count = 0for i in range(len(s) - len(part) + 1):    if s[i:i + len(part)] == part:        count += 1print(count, s.count(part))
3 2

Последнее допустимое начало — len(s) - len(part). Именно поэтому верхняя граница range на 1 больше. Если шаблон длиннее текста, диапазон пуст. С пустым шаблоном count ведёт себя неожиданно: "abc".count("") равно 4 — пустая строка «находится» перед каждым символом и в конце. Если шаблон может оказаться пустым, обработай этот случай отдельно.

Спецсимволы и Unicode

Некоторые символы записывают через обратный слеш, а сами символы — это коды Unicode. \n внутри обычной строки означает перевод строки, \t — табуляцию, \\ — один обратный слеш. Чтобы увидеть представление со специальными символами, используй repr:

s = "A\nB"print(len(s))print(repr(s))print(ord("A"), chr(66))
3 'A\nB' 65 B

Длина 3: A, перевод строки, B. Python хранит строки как Unicode-текст. ord("A") возвращает код символа, chr(66) — символ по коду. Обычная сортировка строк основана на кодах, а не на словарных правилах русского языка.

Тонкости:Unicode, эмодзи и isdigit

Некоторые визуально единые знаки, особенно эмодзи с модификаторами, состоят из нескольких кодовых точек: len считает именно кодовые точки, а не всегда видимые «картинки».

Строковые методы isdigit() и isalpha() работают шире набора английских букв и цифр ASCII. Если условие разрешает строго цифры 0–9, проверяй соответствующий набор. Пустая строка для isdigit() даёт False.

Итог

Теперь ты умеешь доставать из строки символы и куски и собирать из неё новые строки. Вот что понадобится дальше — и в задачах ЕГЭ на строки.

  • ИндексыОт 0 до len(s) - 1, отрицательные — с конца; неверный индекс — IndexError.
  • s[start:stop:step]Граница не входит, как в range; s[::-1] разворачивает строку.
  • НеизменяемостьСимвол заменить нельзя; + и методы строят новую строку.
  • Сборка строкиresult = "" и result += ch в цикле for ch in s; соседние символы — через range(len(s) - 1).
  • Методыlower, strip, replace, find, count возвращают новый результат, строку не меняют.
  • inЕсть ли фрагмент; find даёт −1 при отсутствии, а 0 — это найденное начало.
  • countСчитает без перекрытий; с перекрытиями — проверка каждой позиции срезом.

Проверьте себя

Ответь сначала сам, потом открой ответ.

Вопрос 1

Для s = "PYTHON" что дадут s[1], s[-2] и s[2:4]?

ОтветСкрыть ответ
Ответ

Y, O и TH: индекс 4 в срез s[2:4] не входит.

Вопрос 2

Как одной записью развернуть строку? Что даст "ABCDEFG"[::3]?

ОтветСкрыть ответ
Ответ

s[::-1]; [::3] берёт каждый третий символ — ADG.

Вопрос 3

Почему s[0] = "X" для s = "PYTHON" останавливает программу? Как получить строку «XYTHON»?

ОтветСкрыть ответ
Ответ

Строка неизменяема — TypeError. Новая строка: s = "X" + s[1:].

Вопрос 4

Что напечатает программа?

result = ""for ch in "abc":    result = ch + resultprint(result)
ОтветСкрыть ответ
Ответ

cba: каждый символ ставится перед уже собранной частью, поэтому строка разворачивается.

Вопрос 5

Что вернут "Python".find("th") и "Python".find("x")? Почему проверка if s.find("P"): для s = "Python" сработает неверно?

ОтветСкрыть ответ
Ответ

2 и −1. s.find("P") вернёт 0 — это найденное начало, но 0 в условии ложен. Проверяй "P" in s.

Практика

Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.

Напиши программу: палиндром ли слово

Слово-палиндром читается одинаково слева направо и справа налево. Напиши программу: вводится слово в одном регистре, программа печатает True, если это палиндром, иначе False. Запусти её для слов «топот» и «дом».

Запишите два значения через пробел: для «топот», затем для «дом».

Что напечатает программа?

s = "ИНФОРМАТИКА"print(len(s))print(s[0])print(s[-1])print(s[3])

Запишите напечатанные строки через пробел в порядке вывода.

Что напечатает программа?

s = "ABCDEFG"print(s[2:5])print(s[:4])print(s[::3])print(s[::-2])

Запишите напечатанные строки через пробел в порядке вывода.

Сколько раз «ана» входит в «банана»

Сколько раз «ана» входит в «банана» без перекрытий (как считает count) и с перекрытиями (как считает проверка каждой позиции срезом)?

Запишите два числа через пробел: без перекрытий, затем с перекрытиями.

Что напечатает программа?

print(" Мир ".strip().upper())print("a-b-c".replace("-", "", 1))

Запишите напечатанные строки через пробел в порядке вывода.

Что напечатает программа?

print(ord("a"))print(chr(ord("a") + 2))print("7".zfill(3))

Запишите напечатанные строки через пробел в порядке вывода.

Сколько раз «AA» входит в «AAAAA»

Сколько раз "AA" входит в "AAAAA" по count и с перекрытиями?

Запишите два числа через пробел: по count, затем с перекрытиями.

Напиши программу: сумма цифр через строку

Напиши программу: вводится число, программа находит сумму его цифр, перебирая символы строки циклом for и превращая каждый в int. Запусти её для 9051.

Введите число.