Метод str.index в Python: поиск с гарантией нахождения
Основы метода str.index для строк в Python
Метод str.index() предназначен для поиска подстроки в строке и возвращает индекс первого вхождения. В случае отсутствия подстроки вызывается исключение ValueError. Это главное отличие от метода str.find(), который возвращает -1.
Базовое использование:
s = 'Привет, мир! Программирование на Python.'
index = s.index('мир')
print(index) # 8 (если 'мир' на кириллице, индекс может отличаться)Python strip (метод strip в python)
8
Python повторить строку (повторение строки в python)
Метод принимает три аргумента: sub (искомая подстрока), необязательные start и end (границы поиска). Если подстрока не найдена, программа завершится с ошибкой, поэтому рекомендуется обрабатывать исключение.
Как обработать ситуацию, когда подстрока отсутствует, чтобы программа не падала?
s = 'Python is great'
try:
idx = s.index('Java')
print(f'Найдено на позиции {idx}')
except ValueError:
print('Подстрока не найдена')Tuple в str python (преобразование кортежа в строку в python)
Подстрока не найдена
Python объект в строку (преобразование объекта в строку в python)
Проблема: Если не использовать try/except, при отсутствии подстроки возникает ValueError. Решение - обернуть вызов в блок try. Альтернатива - использовать str.find(), который возвращает -1, но это может быть менее наглядно, когда отсутствие подстроки является ошибкой.
Чем отличается str.index от str.find и когда какой метод стоит применять?
text = 'Hello, World!'
print(text.index('World')) # 7
print(text.find('World')) # 7
print(text.find('Python')) # -1
# print(text.index('Python')) # ValueErrorPython convert string (преобразование строк в python)
7 7 -1
Python str to bytes (преобразование строки в байты в python)
Проблема: Выбор неподходящего метода. index уместен, когда отсутствие подстроки - исключительная ситуация (например, при валидации входных данных). find лучше применять, когда отсутствие является ожидаемым вариантом (например, при условном поиске).
Как искать подстроку, начиная с определённой позиции или в заданном диапазоне?
s = 'раз два три раз два три'
# Найти 'раз' после 5-го символа
print(s.index('раз', 5)) # 16
# Найти 'два' между 4 и 15 символами
print(s.index('два', 4, 15)) # 8функция разделить python (разделение строки на список в python)
16 8
вывести символ строки python (вывод символа строки в python)
Проблема: Ошибка при указании start > end или отрицательных значений. Python интерпретирует отрицательные индексы как смещение от конца строки, что может привести к неожиданному результату. Следует убедиться, что start и end находятся в допустимых границах.
Как найти последнее вхождение подстроки (аналог index, но с конца)?
Для этого существует метод str.rindex(), который возвращает наибольший индекс вхождения.
s = 'один два три один два три'
print(s.rindex('один')) # 16
print(s.rindex('два')) # 20вывести длину строки python (вывести длину строки в python)
16 20
вывести элемент строки python (вывод конкретного символа строки по индексу в python)
Проблема: Путаница между index и rindex. Если требуется именно последнее вхождение, нужно вызывать rindex, иначе результат будет соответствовать первому слева.
Как найти все индексы вхождения подстроки, а не только первый или последний?
text = 'abracadabra'
sub = 'ab'
positions = []
start = 0
while True:
try:
idx = text.index(sub, start)
positions.append(idx)
start = idx + 1
except ValueError:
break
print(positions) # [0, 7]задания на строки python (задания на строки в python)
[0, 7]
Проблема: Бесконечный цикл, если не сдвигать начальную позицию. Решение - увеличивать start на 1 или на длину подстроки, если не нужны перекрывающиеся вхождения.
Расширенные примеры использования str.index
Поиск с учётом регистра
s = 'Python PYTHON python'
# index чувствителен к регистру
print(s.index('Python')) # 0
# print(s.index('python')) # ValueError
# Решение: привести строку к одному регистру
lower_s = s.lower()
print(lower_s.index('python')) # 0 (первое вхождение 'python' после lower)0 0
Поиск одного из нескольких символов (эмуляция)
def index_of_any(text, chars, start=0, end=None):
"""Возвращает индекс первого вхождения любого символа из chars"""
for i, ch in enumerate(text[start:end]):
if ch in chars:
return start + i
raise ValueError('Ни один из символов не найден')
print(index_of_any('hello world', 'wo')) # 66
Поиск в больших текстах (генератор всех позиций)
def all_indices(text, sub):
pos = -1
while True:
try:
pos = text.index(sub, pos + 1)
yield pos
except ValueError:
break
text = 'A man, a plan, a canal, Panama'
for idx in all_indices(text, 'an'):
print(idx, end=' ')2 11 20
Использование index для проверки вхождения с последующим срезом
url = 'https://example.com/api/v1/users'
if 'api' in url:
start = url.index('api')
# Извлекаем путь после 'api'
path = url[start:]
print(path) # api/v1/usersapi/v1/users
Разница в производительности: index vs find для частых вызовов
import timeit
s = 'a' * 10000 + 'b'
# Используем timeit, но для демонстрации приведём пример
# При многократном поиске find может быть быстрее, так как не генерирует исключение в обычном потоке
# Однако для единичного вызова разница незначительна
def test_index():
return s.index('b')
def test_find():
return s.find('b')
print(timeit.timeit(test_index, number=100000)) # ~0.05
print(timeit.timeit(test_find, number=100000)) # ~0.040.052... 0.041...
Поиск подстроки в строках с Unicode (эмодзи)
s = 'Привет ? мир!'
# Эмодзи занимают два суррогатных символа, index работает корректно
print(s.index('?')) # 7 (индекс относительно байтовой позиции, но Python показывает логический индекс)7
Комбинация с rindex для выделения последнего компонента пути
path = '/home/user/projects/script.py'
last_dot = path.rindex('.')
print(path[last_dot:]) # .py
last_slash = path.rindex('/')
print(path[last_slash+1:last_dot]) # script.py script