Строки в Python: обработка текста для ЕГЭ
Срезы, методы и цикл с накопителем: считаем гласные, ищем самую длинную цепочку символов, сдвигаем буквы через ord и chr и красиво выводим ответ через f-строки.
Задание 24 ЕГЭ — одна и та же сцена: в файле лежит строка из нескольких тысяч символов, и нужно найти в ней закономерность. Самая длинная цепочка одинаковых букв, череда цифр, количество пар «буква и цифра». Вручную такое не считают, а программа помещается в десять строк — если владеть срезами, методами, накопителем и кодами символов. Урок собирает кирпичики на коротких словах и показывает ловушки экзамена.
Индексация и срезы
Возьмём слово s = "программа". Символы считаются с нуля: s[0] — это "п", s[4] — снова "р", а последний, девятый по счёту, имеет индекс 8. Отрицательные индексы идут с конца: s[-1] — "а", s[-2] — "м". Длину даёт len: len(s) — 9. Запомни асимметрию: одиночный индекс за границей, s[9] или s[-10], падает с ошибкой IndexError. У срезов характер мягкий — сейчас увидишь.
Срез s[a:b] вырезает символы с индекса a по b - 1: правая граница всегда за кадром, поэтому длина среза равна b - a. Опущенная граница — это «от начала» или «до конца»: s[:4] — первые четыре символа, s[5:] — всё с пятого индекса. Третий параметр — шаг: s[::3] берёт каждый третий символ, а s[::-1] идёт с шагом минус один и возвращает строку наоборот — формулу разворота выучи как таблицу умножения. А s[1:-1] — строка без первого и последнего символа.
| Выражение | Результат | Пояснение |
|---|---|---|
| len(s) | 9 | в слове девять букв |
| s[0] | п | нумерация с нуля |
| s[-1] | а | отрицательный индекс считает с конца |
| s[2:6] | огра | индексы 2, 3, 4, 5; правая граница не входит |
| s[:4] | прог | без левой границы — от начала строки |
| s[5:] | амма | без правой границы — до конца строки |
| s[::3] | пгм | шаг три: индексы 0, 3 и 6 |
| s[::-1] | аммаргорп | шаг минус один — разворот |
| s[1:-1] | рограмм | без первого и последнего символа |
Методы строк
Метод find ищет подстроку и возвращает индекс первого вхождения: "информатика".find("фор") — это 2. Если подстроки нет, вернётся -1: не ошибка, а сигнал для цикла «нашёл — обработал — ищи дальше». Собрат index при неудаче бросает ValueError, поэтому обычно выбирают find. count считает неперекрывающиеся вхождения, replace заменяет сразу все. Главный факт про все методы: оригинал они не трогают. Строки неизменяемы, запись s[0] = "П" вызовет TypeError, а результат нужно присваивать: s = s.replace(...) — иначе замена молча растворится.
split режет строку по разделителю и отдаёт список: "5 10 15".split() — это ["5", "10", "15"]; вызов без аргумента режет по любым пробелам подряд — так читают несколько чисел из строки. Обратная операция — join: "-".join(["2026", "10", "01"]) соберёт дату обратно. strip убирает пробелы по краям — обязательный шаг при чтении файла: справа висит невидимый перевод строки. upper и lower меняют регистр целиком, а оператор in проверяет принадлежность: "и" in "гроза" — True.
| Метод | Что делает | Пример | Результат |
|---|---|---|---|
| find | индекс первого вхождения или -1 | "информатика".find("фор") | 2 |
| count | число неперекрывающихся вхождений | "аааа".count("аа") | 2 |
| replace | новая строка со всеми заменами | "1-2-3".replace("-", "+") | "1+2+3" |
| split | список кусков после разреза | "5 10 15".split() | ["5", "10", "15"] |
| join | строка, склеенная из списка | ".".join(["192", "168", "1", "1"]) | "192.168.1.1" |
| upper и lower | перевод регистра целиком | "PyThOn".upper() | "PYTHON" |
| strip | копия без пробелов по краям | " привет ".strip() | "привет" |
Перебор символов и накопление
Шаблон «цикл плюс накопитель» — главный инструмент задания 24. Заводим счётчик до цикла, проходим for c in s: — переменная c получает сами символы — и обновляем по условию. Подсчёт гласных: s = "гроза" k = 0 for c in s: if c in "аеёиоуыэюя": k += 1 print(k) В "гроза" две гласных, программа выведет 2. Условие меняется, каркас — никогда: цифры ловит c.isdigit(), буквы — c.isalpha(), произвольный набор — проверка in.
Второй типовой сюжет — рекорд: самая длинная цепочка одинаковых символов подряд. Нужны три переменные: prev — предыдущий символ, cur — длина текущей цепочки, best — рекорд. Совпал с prev — cur растёт, не совпал — cur возвращается к единице. После сравнения обновляем рекорд, в конце шага пишем символ в prev. s = "aabbbba" prev = s[0] cur = 1 best = 1 for c in s[1:]: if c == prev: cur += 1 else: cur = 1 if cur > best: best = cur prev = c print(best) Программа выведет 4 — цепочка из четырёх букв "b". Счётчики стартуют с единицы: первый символ уже цепочка, поэтому best = 0 на старте — ошибка.
- Старт: prev = "a", cur = 1, best = 1 — первый символ уже цепочка.
- c = "a": совпал с prev — cur = 2, рекорд обновился, best = 2.
- c = "b": не совпал — cur = 1, новая цепочка; prev стал "b".
- c = "b": совпал — cur = 2, best пока 2.
- c = "b": совпал — cur = 3, best = 3.
- c = "b": совпал — cur = 4, best = 4.
- c = "a": не совпал — cur = 1, но рекорд уже 4. Цикл кончился, print(best) выводит 4.
Колонки cur и best в черновике должны повторить эти шаги.
Условие в if — единственная строка, которая меняется между вариантами задания. Цепочка цифр: c.isdigit() and prev.isdigit(). Чередование «буква и цифра»: c.isdigit() != prev.isdigit() — сравниваются типы, а не символы. Цепочка из набора: c in "ABC" and prev in "ABC". Встречается и вопрос «сколько цепочек длины хотя бы k» — тогда нужна четвёртая переменная — счётчик начал цепочек. Прогоняй каждый вариант на короткой строке руками.
Коды символов: ord и chr
Функция ord возвращает код символа, chr собирает символ из кода: ord("A") — 65, chr(66) — "B". Латиница лежит сплошным куском: заглавные от "A" до "Z" занимают коды 65..90, строчные от "a" до "z" — 97..122. Поэтому «сдвинуть букву по алфавиту» — это арифметика: ord(c) - ord("a") даёт номер буквы, если считать "a" нулевой. Русские строчные от "а" до "я" идут подряд — коды 1072..1103. Строки сравниваются по кодам, поэтому "B" меньше "a": 65 меньше 97.
Шифр Цезаря сдвигает каждую букву на фиксированное число позиций. Формула на один символ: k = 3 c = "x" new = chr((ord(c) - ord("a") + k) % 26 + ord("a")) print(new) Три шага: вычесть базу, прибавить сдвиг, вернуть базу. Остаток % 26 заворачивает переход через конец алфавита: у "x" смещение 23, плюс три — 26, остаток ноль, на выходе "a". Расшифровка отличается только знаком: k меняется на -k. Если переход через конец гарантированно не случится, хватит chr(ord(c) + k).
С русскими буквами та же формула требует внимательности. Букв в алфавите 33, но между "а" и "я" в кодах лежат только 32: "ё" стоит отдельно, с кодом 1105. Первая ловушка: формула с остатком % 33 может выдать код 1104 — символ существует, но это не буква русского алфавита. Если "ё" в данных заведомо не встречается, сдвигают с остатком 32. Вторая ловушка: "ё" ломает и разность — ord("ё") - ord("а") равен 33, хотя по алфавиту "ё" седьмая. Строгая обработка заводит строку-алфавит и ищет позиции буквы через alphabet.find(c). Чаще хватает оговорки про отсутствие "ё".
f-строки и format
Собирать ответ из кусков удобнее всего f-строкой: перед кавычкой ставится буква f, а выражения пишутся в фигурных скобках — f"Цепочка длины {best}" подставит значение переменной. Внутри скобок живут и вычисления: f"{2 * 3 + 1}" даст "7". Для дробных чисел есть округление в выводе: f"{3.14159:.2f}" вернёт "3.14" — две цифры после точки, само число не меняется. f-строки избавляют от склейки со str() и читаются как готовое предложение: print(f"Максимум: {best}"). Метод format делает то же: "{:.2f}".format(3.14159).
Нажми на элемент, затем на категорию. Нажми на разложенный элемент — вернётся в пул.
Разворот строки делает срез . Сдвиг буквы с переходом через конец алфавита: chr((ord(c) - ord("a") + k) % + ord("a")). Метод возвращает индекс первого вхождения или -1.
Банк слов
- Индексация#
- доступ к символу по номеру: s[0] первый, s[-1] последний
- Срез#
- s[a:b] — символы с a по b - 1; третий параметр — шаг
- Неизменяемость#
- методы не меняют оригинал, а возвращают новую строку
- prev, cur, best#
- три переменные шаблона «максимальная цепочка»
- f-строка#
- шаблон вывода с округлением: f"{x:.2f}"
Собери всё в программу для файла: open читает строку, strip чистит края, дальше — цикл с prev, cur и best, в конце печать через f-строку. Самоконтроль без компьютера: "программа"[2:6] — это "огра", "аааа".count("аа") — два, в "гроза" две гласных, шифр со сдвигом 3 превращает "x" в "a". Если проверки сошлись — шаблоны урока усвоены.
Проверь себя
Клавиши 1–9 выбирают вариант, Enter — «Проверить»
1 Что вернёт выражение "молоко".find("ол")?
2 Какие вызовы вернут строку?
3 Строка s = "программа". Что выведет команда print(s[3:6])? Впиши символы без кавычек.
4 Значение выражения "аааа".count("аа") равно 3.
5 Расставь действия алгоритма поиска самой длинной цепочки одинаковых символов.
6 Разложи вызовы по типу результата.
Разложи элементы по категориям: нажми на элемент, потом на категорию.
7 Дополни правила работы со строками.
Выбери подходящее слово в каждом пропуске.
Строки неизменяемы: метод replace возвращает строку, а оригинал не трогает. Метод find при неудаче вернёт , а его собрат index бросит исключение. Перевернуть строку помогает срез .
Было понятно? Скажи — так мы видим, какие темы переписать.
Частые вопросы
Почему "аааа".count("аа") даёт 2, а не 3?
Метод считает неперекрывающиеся вхождения: найдя "аа" с нулевой позиции, поиск продолжается с индекса 2. Вариант, начинающийся с индекса 1, целиком лежит внутри уже найденного куска и не учитывается, поэтому остаются только позиции 0 и 2.
Чем find отличается от index?
Оба возвращают индекс первого вхождения подстроки. Разница проявляется при неудаче: find вернёт -1, а index бросит ValueError, который без try и except уронит программу. В задачах с файлом обычно берут find — проверка результата на -1 проще обработки исключения.
Можно ли заменить один символ строки присваиванием?
Нет: строки неизменяемы, запись s[0] = "П" вызовет TypeError. Собери новую строку и присвой её той же переменной: s = "П" + s[1:] меняет первый символ через склейку. Тот же принцип у replace и upper — они возвращают копию, а оригинал не трогают.
Почему для цепочки нужны ровно три переменные?
prev отвечает за сравнение соседей, cur — за длину текущей цепочки, best — за рекорд. Без prev непонятно, с чем сравнивать текущий символ, без cur — не от чего считать рекорд, а без best ответ сотрётся при следующем сбросе счётчика. Три переменные заводят до цикла и инициализируют первым символом и единицами.