При работе со строками довольно часто возникает необходимость найти нужное сочетание символов внутри строки или подсчитать, сколько раз оно встречается в этой строке. Также часто требуется убедиться в том, что строка соответствует нужному формату, например, состоит только из чисел или начинается с определённой строки.

Поиск подстроки в строке

Для поиска подстроки в строке Python предоставляет два основных метода: str.index() и str.find(). Оба метода предназначены для обнаружения первого вхождения указанной подстроки и возвращают индекс начала этого вхождения.

Ключевое различие между этими двумя методами заключается в их поведении, когда подстрока не найдена:

  • метод str.index() в такой ситуации вызовет исключение ValueError, что приведёт к прерыванию выполнения программы;
  • метод str.find() просто вернёт -1, и программа дальше продолжит работу.

Методы

str.index(sub, start=0, end=None)

str.find(sub, start=0, end=None)

Описание

Возвращают начальный индекс первого вхождения подстроки sub в строку str

Параметры

  • sub – искомая подстрока

Необязательные параметры:

  • start – индекс начала среза, в котором ищется подстрока sub. По умолчанию start=0
  • end – индекс конца среза, в котором ищется подстрока sub. По умолчанию end=None (до конца строки)

Возвращаемое значение

Целое число

По умолчанию поиск подстроки осуществляется по всей строке:

proverb = "Век живи — Век учись" 
print(proverb.index("Век")) 
# Вывод: 0

citate = "Один за всех, все за одного"
print(citate.find("за")) 
# Вывод: 5

Но оба метода поддерживают ограничение диапазона поиска с помощью среза [start:end]:

proverb = "Век живи — Век учись" 
print(proverb.index("Век", 6, 14)) 
# Вывод: 11

citate = "Один за всех, все за одного"
print(citate.find("за", 15, 21)) 
# Вывод: 18

В случае отсутствия искомой подстроки в строке метод str.index() вызовет исключение ValueError, а метод str.find() просто вернёт -1:

proverb = "Век живи — Век учись" 
print(proverb.index("бездельничай")) 
# Ошибка: ValueError: substring not found

citate = "Один за всех, все за одного"
print(citate.find("д'Артаньян")) 
# Вывод: -1 

Также у обоих методов есть варианты с префиксом «r», которые начинают поиск не с начала строки, а с конца (справа), поэтому возвращают индекс последнего вхождения подстроки.

Методы

str.rindex(sub, start=0, end=None)

str.rfind(sub, start=0, end=None)

Описание

Возвращают начальный индекс последнего вхождения подстроки sub в строку str

Параметры

  • sub – искомая подстрока

Необязательные параметры:

  • start – индекс начала среза, в котором ищется подстрока sub. По умолчанию start=0
  • end – индекс конца среза, в котором ищется подстрока sub. По умолчанию end=None (до конца строки)

Возвращаемое значение

Целое число

Так, если методы str.index() и str.find() возвращают наименьший индекс начала подстроки, то методы str.rindex() и str.rfind() наибольший:

proverb = "Семь раз отмерь, один раз отрежь" 
print(proverb.index("раз")) 
# Вывод: 5
print(proverb.rindex("раз")) 
# Вывод: 22

citate = "Казань брал, Астрахань брал, Ревель брал, Шпака — не брал"
print(citate.find("брал")) 
# Вывод: 7
print(citate.rfind("брал")) 
# Вывод: 53 

В случае отсутствия искомой подстроки в строке метод str.rindex() аналогично вызывает исключение ValueError, а метод str.rfind() возвращает -1:

proverb = "Семь раз отмерь, один раз отрежь" 
print(proverb.rindex("Восемь")) 
# Ошибка: ValueError: substring not found

citate = "Казань брал, Астрахань брал, Ревель брал, Шпака — не брал"
print(citate.rfind("захватил"))
# Вывод: -1

Подсчёт количества вхождений подстроки в строку

Когда необходимо не просто найти индекс начала вхождения подстроки, а посчитать общее количество её вхождений, используется метод str.count().

Метод

str.count(sub, start=0, end=None)

Описание

Возвращает количество вхождений подстроки sub в строку str

Параметры

  • sub – подсчитываемая подстрока

Необязательные параметры:

  • start – индекс начала среза, в котором ищется подстрока sub. По умолчанию start=0
  • end – индекс конца среза, в котором ищется подстрока sub. По умолчанию end=None (до конца строки)

Возвращаемое значение

Целое число

По умолчанию подсчёт вхождений осуществляется по всей строке:

citate = "Неважно, сколько раз вы падали; важно, сколько раз вы поднимались"
print(citate.count("сколько")) 
# Вывод: 2

Но как и поиск, область подсчёта можно ограничить помощью среза [start:end]:

citate = "Неважно, сколько раз вы падали; важно, сколько раз вы поднимались"
print(citate.count("сколько", 2, 18))
# Вывод: 1

Проверка регистра символов строки

Метод str.islower() проверяет регистр всех букв в строке на принадлежность к нижнему регистру, а метод str.isupper() – к верхнему. Как и большинство методов (и функций), которые что-либо проверяют (возвращают True или False), они начинаются со слова is (с англ. – быть, являться).

Метод

str.islower()

Описание

Возвращает True, если все буквы в строке str маленькие, иначе – False

Возвращаемое значение

True или False

Метод

str.isupper()

Описание

Возвращает True, если все буквы в строке str заглавные, иначе – False

Возвращаемое значение

True или False

Если все буквы строки находятся в проверяемом регистре, то оба метода возвращают True:

username = input("Введите имя пользователя: ")
if username.islower():
    print("хорошее маленькое имя пользователя")
elif username.isupper():
    print("ХОРОШЕЕ БОЛЬШОЕ ИМЯ ПОЛЬЗОВАТЕЛЯ")
# Ввод: Введите имя пользователя: повелитель_кексиков
# Вывод: хорошее маленькое имя пользователя

Но если строка состоит одновременно из заглавных и маленьких букв, то оба метода вернут False:

message = "Что делаешь?"
print(message.islower())
# Вывод: False
print(message.isupper())
# Вывод False

Проверка типа символов строки

Для проверки того, являются ли все символы строки только буквами используется метод str.isalpha(), а только цифрами – метод str.isdigit().

Метод

str.isalpha()

Описание

Возвращает True, если строка str состоит из букв, иначе – False

Возвращаемое значение

True или False

Метод

str.isdigit()

Описание

Возвращает True, если строка str состоит из цифр, иначе – False

Возвращаемое значение

True или False

Например, введённое пользователем имя не должно содержать никаких символов, кроме букв, поэтому его можно проверить с помощью метода str.isalpha():

name = input("Введите имя: ")
if not name.isalpha():
    print("Имя может содержать только буквы!")
else:
    print("Какое хорошее имя!")
# Ввод: Введите имя: Е102-гамма
# Вывод: Имя может содержать только буквы!

Возраст же может представлять собой только число, поэтому для проверки корректности его ввода используем метод str.isdigit():

age = input("Введите возраст: ")
if not age.isdigit():
    print("Возраст может содержать только цифры!")
else:
    print("Какой чудесный возраст!")
# Ввод: Введите возраст: 100
# Вывод: Какой чудесный возраст!

Но если строка может включать в себя как буквы, так и из цифры, то проверить это можно с помощью метода str.isalnum().

Метод

str.isalnum()

Описание

Возвращает True, если строка str состоит из букв или цифр, иначе – False

Возвращаемое значение

True или False

Это метод не требует одновременного наличия букв и цифр в строке и вернёт True как в случае, если строка состоит только из букв, так и если она состоит только из цифр:

password = input("Введите пароль: ")
if not password.isalnum():
    print("Пароль может содержать только буквы или цифры!")
else:
    print("Это самый лучший пароль на свете!")
# Ввод: Введите пароль: qwerty123
# Вывод: Это самый лучший пароль на свете!

Все методы проверки типа символов в строке возвращают False, если строка содержит пробелы или другие не буквенно-цифровые символы. Однако метод str.isspace() позволяет проверить строку на то, состоит ли она только из одних пробелов.

Метод

str.isspace()

Описание

Возвращает True, если строка str состоит из пробелов, иначе – False

Возвращаемое значение

True или False

Данный метод вернёт True, в том числе, если строка содержит символы табуляции или перевод на новую строку:

username = "  \t \n   "
print(username.isspace()) 
# Вывод: True

Проверка начала и конца строки

Также можно проверить строку на соответствие определённому шаблону. Так, метод str.startswith() проверяет начинается ли строка с указанной подстроки (префикса), а метод str.endswith(), наоборот, проверяет заканчивается ли она указанной подстрокой (суффиксом).

Метод

str.startswith(prefix, start=0, end=None)

Описание

Возвращает True, если строка str начинается на подстроку prefix, иначе – False

Параметры

  • prefix – строка-префикс, которой предполагаемо начинается строка

Необязательные параметры:

  • start – индекс начала среза, в котором проверяется наличие строки-префикса. По умолчанию start=0
  • end – индекс конца среза, в котором проверяется наличие строки-префикса. По умолчанию end=None (до конца строки)

Возвращаемое значение

True или False

Метод

str.endswith(suffix, start=0, end=None)

Описание

Возвращает True, если строка str оканчивается на подстроку suffix, иначе – False

Параметры

  • suffix – строка-суффикс, которой предполагаемо заканчивается строка

Необязательные параметры:

  • start – индекс начала среза, в котором проверяется наличие строки-суффикса. По умолчанию start=0
  • end – индекс конца среза, в котором проверяется наличие строки-суффикса. По умолчанию end=None (до конца строки)

Возвращаемое значение

True или False

Например, так можно проверить фамилию по ФИО:

name = input("Введите ФИО: ")
if name.startswith("Романов"):
    print("Да это же Романовы!")
elif name.startswith("Рюрикович"):
    print("Да это же Рюриковичи!")
# Ввод: Введите ФИО: Романова Е.А.
# Вывод: Да это же Романовы!

Или проверить расширение файла:

filename = input("Введите название файла: ")
if filename.endswith(".py"):
    print("Это файл с кодом на Python")
elif filename.endswith(".docx"):
    print("Это файл с документом MS Word")
# Ввод: Введите название файла: task.py
# Вывод: Это файл с кодом на Python

Как и другие методы поиска подстроки, методы str.startswith() и str.endswith() поддерживают ограничение области поиска начала и конца строки с помощью среза [start:end]:

article = "Cамая лучшая шинковка для капусты"
print(article.startswith("Самая", 6))
# Вывод: False
print(article.endswith("капусты", 5, 15))
# Вывод: False

Примеры

Пример 1. Поиск ключевого слова в отзыве

Программа проверяет, содержит ли отзыв клиента упоминание о доставке и где именно оно находится:

review = "Очень вкусная пицца, но хотелось бы более быструю доставку..."

# Так как слов "доставка" может изменяться по падежам, то ищем слово "доставк"
delivery_index = review.find("доставк")

if delivery_index != -1:
    print(f"Слово 'доставка' найдено в отзыве по индексу: {delivery_index}")
else:
    print("Слово 'доставка' не найдено в отзыве")

Вывод:

Слово 'доставка' найдено в отзыве по индексу: 50

Пример 2. Анализ текста

Онлайн-сервис подсчитывает количество предложений и символов (без пробела) в тексте:

text = "Обаятельный молодой человек по имени Джимми Тесайгер пронесся вниз по
большой лестнице особняка Чимниз, перепрыгивая через две ступеньки. Его появление
было столь неожиданным, что он столкнулся с Тредуэллом, величественным дворецким, в тот момент, когда последний пересекал зал, неся новые порции горячего кофе. Никто не пострадал только благодаря изумительному присутствию духа и необычайной ловкости дворецкого."
 
# Подсчет количества предложений по знакам препинания в конце предложения
sentences = text.count(".") + text.count("!") + text.count("?")
print(f"Предложений: {sentences}")
 
# Подсчёт количества символов (без прлобела)
chars = 0
for word in text.split():  # Цикл проходит по каждому слову
    for letter in word:  # Цикл проходит по каждому символу в слове
        chars += 1
print(f"Символов (без пробела): {chars}")  

Вывод:

Предложений: 3
Символов (без пробела): 360

Пример 3. Проверка корректности адреса электронной почты

При регистрации нового пользователя система проверяет на корректность введённый адрес электронный почты.

user_email = input("Введите адрес электронной почты: ")
is_valid_email = (
    user_email.count("@") == 1  # Одна @
    and not user_email.startswith("@")  # Не начинается с @
    and not user_email.endswith("@")  # Не заканчивается на @
)
 
if is_valid_email:
    print(f"Спасибо за регистрацию! Пароль придёт на почту {user_email}")
else:
    print("Некорректный адрес электронной почты")

Вывод:

Введите адрес электронной почты: cutedragon777@example.ru
Спасибо за регистрацию! Пароль придёт на почту cutedragon777@example.ru

Итоги

Методы поиска и проверки строк

Метод

Описание

str.index(sub, start=0, end=None)

Возвращает начальный индекс первого вхождения подстроки sub в строку str. Если подстрока не найдена, то вызывает исключение ValueError

str.find(sub, start=0, end=None)

Возвращают начальный индекс первого вхождения подстроки sub в строку str. Если подстрока не найдена, то возвращает -1

str.rindex(sub, start=0, end=None)

Возвращает начальный индекс последнего вхождения подстроки sub в строку str. Если подстрока не найдена, то вызывает исключение ValueError

str.rfind(sub, start=0, end=None)

Возвращают начальный индекс последнего вхождения подстроки sub в строку str. Если подстрока не найдена, то возвращает -1

str.count(sub, start=0, end=None)

Возвращает количество вхождений подстроки sub в строку str

str.islower()

Возвращает True, если все буквы в строке str маленькие, иначе – False

str.isupper()

Возвращает True, если все буквы в строке str заглавные, иначе – False

str.isalpha()

Возвращает True, если строка str состоит из букв, иначе – False

str.isdigit()

Возвращает True, если строка str состоит из цифр, иначе – False

str.isalnum()

Возвращает True, если строка str состоит из букв или цифр, иначе – False

str.isspace()

Возвращает True, если строка str состоит из пробелов, иначе – False

str.startswith(prefix, start=0, end=None)

Возвращает True, если строка str начинается на подстроку prefix, иначе – False

str.endswith(suffix, start=0, end=None)

Возвращает True, если строка str оканчивается на подстроку suffix, иначе – False

Задания для самопроверки

1. Найдите первое вхождение слова "мир" в строке "Привет, мир! Как дела, мир?" и выведите его на экран. Поиск должен вестись с индекса 7.

text = "Привет, мир! Как дела, мир?"
index = text.find("мир", 7)
print(index)  
# Вывод: 18

2. Какие методы используются для поиска последнего вхождения подстроки в строке? Как они ведут себя, если подстрока не найдена?

Для поиска последнего вхождения подстроки используются методы str.rindex() и str.rfind(). Если подстрока не найдена, метод str.rindex() вызывает исключение ValueError, а метод str.rfind() возвращает -1.

3. Используйте метод str.count() и выведите на экран, сколько раз символ "!" встречается в строке "Ура!!! Получилось!".

text = "Ура!!! Получилось!"
count = text.count("!")
print(count)  
# Вывод: 4

4. Что вернут методы str.islower() и str.isupper() для строки "Вконтакте"?

vk = "Вконтакте"
print(vk.islower())
# Вывод: False
print(vk.isupper())
# Вывод: False

Оба метода вернут False, так как строка содержит как заглавные, так и строчные буквы.

5. Запросите у пользователя строку с почтовыми индексом. Если она состоит только из цифр, то выведите на экран строку "Введён корректный почтовый индекс", иначе – "Почтовый индекс должен состоять только из цифр".

Пример входных данных

Пример выходных данных

160789

Введён корректный почтовый индекс

34POST

Почтовый индекс должен состоять только из цифр

985172

Введён корректный почтовый индекс

postal_code = input("Введите почтовый индекс: ")
if postal_code.isdigit():
    print("Введён корректный почтовый индекс")
else:
    print("Почтовый индекс должен состоять только из цифр")

6. Запросите у пользователя строку с именем файла. Если она заканчивается расширением ".txt", то выведите на экран строку "Это текстовый файл", иначе – "Это не текстовый файл".

Пример входных данных

Пример выходных данных

task.txt

Это текстовый файл

cake.jpeg

Это не текстовый файл

passwords.txt

Это текстовый файл

file_name = input("Введите имя файла: ")
if file_name.endswith(".txt"):
    print("Это текстовый файл")
else:
    print("Это не текстовый файл")