Python string replace: как заменить подстроку
Метод replace() в Python заменяет в строке все вхождения одной подстроки на другую и возвращает новую строку. Из статьи вы узнаете синтаксис и параметр count, способы удалить символы, сделать несколько замен за раз, заменить только последнее вхождение и когда вместо replace() лучше взять translate() или регулярные выражения.

Содержание статьи
Синтаксис и параметры
Метод вызывается у строки и принимает два обязательных аргумента и один необязательный:
str.replace(old, new, count=-1)old- подстрока, которую нужно найти. Это может быть один символ или целое слово;new- подстрока для подстановки, в том числе пустая строка;count- максимальное число замен. По умолчанию -1, то есть заменяются все вхождения.
Начиная с Python 3.13 count можно передавать по имени: s.replace('a', 'b', count=1). В более ранних версиях он принимается только позиционно, а вызов с именем дает TypeError.
text = 'bat ball'
print(text.replace('b', 'c')) # cat call
print(text.replace('ball', 'cap')) # bat capПоиск идет слева направо, а найденные фрагменты не перекрываются. Например, 'aaaa'.replace('aa', 'b') вернет 'bb', а не три замены.
Строка не меняется на месте
Строки в Python неизменяемы, поэтому replace() всегда создает новый объект. Самая частая ошибка новичков - вызвать метод и не сохранить результат:
city = 'Санкт Петербург'
city.replace(' ', '-') # результат потерян
print(city) # Санкт Петербург
city = city.replace(' ', '-')
print(city) # Санкт-ПетербургЕсли подстрока не найдена, метод вернет строку с тем же содержимым, ошибки не будет. Поэтому заранее проверять вхождение через in перед заменой не нужно. О способах поиска подстроки рассказано в отдельной статье про поиск подстроки.
Ограничение числа замен
Параметр count позволяет заменить только первые N совпадений. Это удобно, когда нужно поменять первое вхождение, а остальные оставить.
log = 'ERROR: disk ERROR: net ERROR: cpu'
print(log.replace('ERROR', 'WARN', 1))
# WARN: disk ERROR: net ERROR: cpu
print(log.replace('ERROR', 'WARN', 2))
# WARN: disk WARN: net ERROR: cpu
print(log.replace('ERROR', 'WARN', 0))
# ERROR: disk ERROR: net ERROR: cpuПри count=0 замен нет совсем. Отрицательное значение означает "заменить все".
Замена последнего вхождения
Отдельного параметра для замены с конца у replace() нет. Задачу решает сочетание rsplit() и join(): строка разрезается по последнему вхождению и склеивается обратно с новой подстрокой.
path = 'docs/report.old.old'
result = '.new'.join(path.rsplit('.old', 1))
print(result) # docs/report.old.newУдаление символов из строки
Если передать пустую строку в качестве new, найденные фрагменты просто исчезнут. Так удаляют пробелы, переносы строк, знаки валют и другой мусор.
price = '1 299 руб.'
print(price.replace(' ', '').replace('руб.', '')) # 1299
line = 'строка\r\n'
print(repr(line.replace('\r', ''))) # 'строка\n'Чтобы убрать пробелы только по краям строки, а не внутри, используйте strip(). replace(' ', '') удалит все пробелы, включая пробелы между словами.
Несколько замен за один раз
replace() принимает только одну пару "что на что". Для нескольких замен есть три подхода.
Цепочка вызовов и словарь
Каждый вызов возвращает строку, поэтому методы можно вызывать подряд. При большом числе пар их удобнее хранить в словаре и обходить циклом.
phone = '+7 (999) 123-45-67'
digits = phone.replace(' ', '').replace('(', '').replace(')', '').replace('-', '')
print(digits) # +79991234567
abbr = {'т.е.': 'то есть', 'т.к.': 'так как'}
text = 'Не работает, т.к. нет сети, т.е. офлайн'
for old, new in abbr.items():
text = text.replace(old, new)
print(text) # Не работает, так как нет сети, то есть офлайнУ цикла есть ловушка: замены выполняются по очереди, и результат одной может попасть под следующую. Например, при парах a на b и b на c буква a в итоге станет c.
translate() для отдельных символов
Когда нужно заменить или удалить много одиночных символов, быстрее и надежнее метод translate() с таблицей из str.maketrans(). Все замены делаются за один проход, поэтому описанной выше ловушки нет.
table = str.maketrans({'ё': 'е', 'Ё': 'Е', ';': ','})
print('Ёлка; ёж'.translate(table)) # Елка, еж
no_digits = str.maketrans('', '', '0123456789')
print('a1b2c3'.translate(no_digits)) # abcre.sub() для шаблонов
Регулярные выражения нужны, если подстрока не фиксирована: любые цифры, несколько пробелов подряд, слово в любом регистре. Функция re.sub() из модуля re заменяет все совпадения с шаблоном.
import re
print(re.sub(r'\s+', ' ', 'много пробелов тут')) # много пробелов тут
print(re.sub('python', 'Python', 'PYTHON и python', flags=re.I))
# Python и Python
print(re.sub(r'\d', '*', 'Карта 4276 1234')) # Карта **** ****Что выбрать для замены
Сравнение способов поможет быстро подобрать инструмент под задачу.
| Задача | Способ | Особенность |
|---|---|---|
| Заменить фиксированную подстроку | replace() | Самый простой и быстрый вариант |
| Заменить первые N вхождений | replace(old, new, n) | Отсчет идет слева |
| Заменить последнее вхождение | rsplit() и join() | Отдельного метода нет |
| Много одиночных символов | translate() | Один проход, замены не мешают друг другу |
| Шаблон или любой регистр | re.sub() | Гибко, но медленнее replace() |
Другие операции со строками собраны в справочнике по методам строк.
Частые вопросы
Ответы на вопросы, которые чаще всего задают о замене текста в Python.
Почему replace() не изменил строку?
Метод возвращает новую строку и не трогает исходную. Присвойте результат: s = s.replace('a', 'b').
Можно ли заменить без учета регистра?
replace() различает регистр: 'Python' и 'python' для него разные строки. Для замены без учета регистра используйте re.sub() с флагом re.IGNORECASE.
Как заменить символ по индексу?
Строку нельзя изменить по индексу, присваивание s[0] = 'X' вызовет TypeError. Соберите новую строку срезами: s = s[:i] + 'X' + s[i + 1:].
Как применить replace() ко всем строкам списка?
Используйте генератор списка: [item.replace(',', '.') for item in values]. У самого списка метода replace() нет.
Что будет, если old - пустая строка?
Новая подстрока вставится между всеми символами, а также в начало и конец: 'abc'.replace('', '-') вернет '-a-b-c-'.