Строки встречаются ребёнку раньше любых других данных: первая же программа что-то печатает, вторая что-то спрашивает. Но работать с ними всерьёз начинают позже, и тогда выясняется, что строка умеет значительно больше, чем просто выводиться на экран.
Ниже справочник по тому, что действительно используется: как достать часть строки, какие методы нужны в задачах, как собрать текст из чисел и почему попытка изменить одну букву заканчивается ошибкой. Примеры короткие — их удобно набрать и сразу посмотреть результат.
Строка — это последовательность
К каждому символу можно обратиться по номеру, так же как к элементу списка. Нумерация с нуля, отрицательные номера считаются с конца.
slovo = 'Python'
print(slovo[0]) # P
print(slovo[-1]) # n
print(slovo[1:4]) # yth
print(slovo[::-1]) # nohtyP
print(len(slovo)) # 6
Срезы работают так же, как в списках: правая граница не входит, поэтому [1:4] даёт три символа. Запись [::-1] переворачивает строку — кратчайший способ проверить, является ли слово палиндромом, и один из первых трюков, который дети переписывают друг у друга.
Методы, которые нужны на самом деле
| Метод | Что делает | Пример результата |
|---|---|---|
upper() | все заглавные | PYTHON |
lower() | все строчные | python |
capitalize() | первая заглавная | Python |
strip() | убирает пробелы по краям | текст без отступов |
replace(a, b) | заменяет все вхождения | новая строка |
split() | режет на список слов | список |
join(spisok) | склеивает список в строку | строка |
find(a) | номер символа или -1 | число |
count(a) | сколько раз встретилось | число |
startswith(a) | начинается ли с | True или False |
isdigit() | состоит ли из цифр | True или False |
Две последние строки полезнее, чем кажутся. Проверка isdigit() позволяет запросить у пользователя число и не упасть, если он ввёл слово: сначала проверяем, потом преобразуем. Без неё первая же программа с вводом падает, стоит кому-то нажать Enter не ту клавишу.
Метод find() отличается от похожего index() одной деталью: когда ничего не найдено, первый тихо возвращает минус единицу, а второй останавливает программу ошибкой. Для проверки «есть ли такое вообще» надёжнее взять in: запись 'a' in slovo читается лучше обоих.
f-строки: сборка текста из чисел
Самый удобный способ собрать сообщение — поставить перед кавычками букву f и вписать переменные прямо в текст, в фигурных скобках.
imia = 'Olia'
ochki = 120
print(f'{imia} набрала {ochki} баллов')
print(f'Среднее: {ochki / 7:.2f}')
Вторая строка показывает заодно форматирование: двоеточие и .2f означают «показать два знака после запятой». Без этого деление даёт длинный хвост цифр, который в отчёте выглядит неопрятно.
До f-строк текст собирали плюсом, и этот способ до сих пор встречается в старых учебниках. Проблема в том, что плюс не умеет складывать текст с числом: 'Баллов: ' + 120 даёт ошибку, и приходится писать str(120) вокруг каждого числа. С f-строкой преобразование происходит само.
Строку нельзя изменить
Вот главная неожиданность темы. Попытка заменить один символ на месте не работает вообще:
slovo = 'Python'
slovo[0] = 'J' # ошибка
slovo = 'J' + slovo[1:] # а так правильно
Строки в Python неизменяемы: любой метод не правит имеющуюся, а возвращает новую. Поэтому запись slovo.upper() сама по себе ничего не меняет — результат надо куда-то положить, хотя бы обратно в ту же переменную. Это самая частая причина, по которой «метод не сработал»: он сработал, просто результат никуда не записали.
Списки в этом устроены наоборот, и ребёнку полезно увидеть оба случая рядом: тогда правило запоминается как отличие, а не как отдельный факт про строки.
input всегда даёт текст
Ещё одно место, где программа падает на ровном месте. Всё, что введено с клавиатуры, приходит строкой, даже если это цифры.
vozrast = input('Сколько тебе лет? ')
print(vozrast + 1) # ошибка
print(int(vozrast) + 1) # работает
Преобразование int() нужно каждый раз, когда введённое собираются считать. Если число дробное, берётся float(). А если пользователь ввёл слово, int() тоже падает — и именно здесь пригождается упомянутый выше isdigit().
Перебор строки циклом
Строка перебирается так же, как список, и это тот момент, когда две темы наконец сходятся. Цикл проходит по символам, а не по словам, и этого хватает для большинства учебных задач.
slovo = 'programmirovanie'
glasnye = 'aeiouyаеёиоуыэюя'
schetchik = 0
for bukva in slovo:
if bukva in glasnye:
schetchik = schetchik + 1
print(schetchik)
Задача про подсчёт гласных выглядит школьной, но внутри неё три важные вещи сразу: перебор, проверка на вхождение и накопитель. Поэтому мы ставим её в программу именно после строк — она собирает воедино то, что до этого существовало по отдельности.
Если нужен не сам символ, а его номер, удобнее enumerate: он отдаёт пару «номер и символ» за один проход, и не приходится вести отдельную переменную-счётчик.
Длинный текст и перенос строки
Для многострочного текста берут три кавычки вместо одной. Всё, что внутри, сохраняется как есть, вместе с переносами:
pravila = '''Правила игры:
1. Три попытки
2. Подсказка стоит балл'''
print(pravila)
Второй способ — специальная пара символов внутри обычной строки, означающая переход на новую строку. Выглядит она как обратная косая черта с буквой n, и именно из-за неё чаще всего возникает путаница: в тексте её видно двумя символами, а на экране она превращается в перенос.
Ребёнку полезно сразу объяснить, что это не опечатка, а команда внутри текста. Рядом живут ещё две такие же: табуляция и сама обратная косая черта, которую, чтобы напечатать, приходится писать дважды.
split и join: туда и обратно
Эти два метода ходят парой и вместе решают большинство задач с текстом. Первый разрезает строку на список, второй собирает список обратно в строку.
predlozhenie = 'kot sidit na okne'
slova = predlozhenie.split() # список из четырёх слов
print(len(slova)) # 4
print(' '.join(slova[::-1])) # слова в обратном порядке
Без аргументов split() режет по любым пробелам, и лишние пробелы между словами его не смущают. Можно указать, по чему резать: split(',') разберёт строку с запятыми, и именно так читают простые таблицы.
Запись ' '.join(slova) сначала выглядит перевёрнутой: разделитель стоит впереди, а список в скобках. Логика в том, что склеивает именно разделитель, и это тот редкий случай, когда объяснение «так решили» работает хуже, чем просто запомнить форму.
Одна задача целиком
Чтобы методы перестали быть перечнем, полезно собрать из них что-то рабочее. Классическая задача — посчитать, сколько раз каждое слово встречается в тексте. Она короткая, и в ней работает всё сразу: приведение регистра, резка на слова, словарь как накопитель.
tekst = 'Kot sidit. Kot spit. Sobaka begaet.'
slova = tekst.lower().replace('.', ' ').split()
chastota = {}
for slovo in slova:
chastota[slovo] = chastota.get(slovo, 0) + 1
print(chastota)
Вторую строку стоит разобрать отдельно: методы вызываются цепочкой, слева направо. Сначала всё становится строчными буквами, потом точки заменяются пробелами, и только после этого строка режется на слова. Поменять порядок — и точка приклеится к слову, а kot и Kot посчитаются как разные.
Именно здесь видно, зачем был нужен get из словарей: без него первое же новое слово остановило бы программу ошибкой.
Три ошибки, которые повторяются
Первая: slovo.replace('a', 'o') написано отдельной строкой, а результат никуда не сохранён. Выглядит как «метод не работает».
Вторая: сравнение с разным регистром. Строка 'Да' не равна 'да', и викторина не засчитывает правильный ответ. Лечится приведением обеих сторон к нижнему регистру перед сравнением.
Третья: невидимые пробелы. Ответ, скопированный из другого места, часто приходит с пробелом на конце, и сравнение проваливается без видимой причины. Привычка писать .strip() сразу после input() снимает эту проблему навсегда.
Строки хорошо ложатся рядом со списками — их справочник здесь, а перебирать и то, и другое удобно циклом for. Что ломается в первых программах чаще всего, собрано в типичных ошибках новичков.