Как пройтись по строке в Python по символам?
Пришёл из C-подобного языка, там бегал по строке индексами s[i]. В Python пробую так же и не уверен, что это правильный способ. Как принято перебирать символы? И ещё: хочу заменить первый символ через s[0] = 'X', а получаю ошибку — почему строку нельзя так менять?
2 ответа
В Python строка — это итерируемый объект, поэтому самый чистый способ — идти прямо по символам, без индексов:
s = "кот"
for ch in s:
print(ch)
# к
# о
# т
Индекс тут вообще не нужен. Если он всё же нужен (например, печатать позицию), бери enumerate, а не range(len(...)):
for i, ch in enumerate(s):
print(i, ch) # 0 к / 1 о / 2 т
Вариант с индексами тоже рабочий, просто менее идиоматичный:
for i in range(len(s)):
print(s[i])
Срезы — отдельная мощная штука, берут подстроки без цикла:
s = "программа"
print(s[0]) # п (один символ)
print(s[0:4]) # прог (с 0 по 4, не включая 4)
print(s[-1]) # а (последний)
print(s[::-1]) # аммаргорп (разворот)
Теперь почему s[0] = 'X' падает. Строки в Python неизменяемые (immutable), как и числа. Это TypeError: 'str' object does not support item assignment. Любая «модификация» на деле создаёт новую строку:
s = "hello"
s = "X" + s[1:]
print(s) # Xello
Если надо много мелких правок — собери символы в список, поменяй, склей обратно:
chars = list("hello")
chars[0] = "X"
result = "".join(chars)
print(result) # Xello
Неизменяемость не баг, а фича: строки можно класть ключами словаря и в множества, и они безопасно шарятся между частями программы.
Один нюанс про "символы". Итерация идёт по кодовым точкам Unicode, и для обычных букв всё интуитивно. Но с эмодзи и составными символами один «видимый знак» может быть несколькими кодовыми точками:
for ch in "a👍":
print(ch) # a, потом 👍 — тут ок
Для базовых задач (русский/латиница) можно не думать об этом. Но если будешь резать строки с эмодзи и флагами по индексам — могут разъехаться. Тогда смотри в сторону библиотеки regex с поддержкой графемных кластеров.