На этом шаге мы приведем код, решающий эту задачу, и прокомментируем его.
Наша цель - найти конкретный текст внутри многострочного строкового значения. Затем необходимо вернуть его непосредственное окружение в виде 18 символов, окружающих найденное вхождение. Извлечение окружения вместе с искомым текстом позволяет увидеть текстовый контекст найденной строки - подобно тому, как Google выводит фрагменты текста, окружающие искомое ключевое слово. В примере 2.5 мы ищем строку символов 'SQL' в письме Amazon к акционерам - вместе с непосредственным ее окружением в виде 18 окружающих строку 'SQL' символов.
## Данные letters_amazon = ''' We spent several years building our own database engine, Amazon Aurora, a fully-managed MySQL and PostgreSQL-compatible service with the same or better durability and availability as the commercial engines, but at one-tenth of the cost. We were not surprised when this worked. ''' ## Однострочник find = lambda x, q: x[x.find(q) - 18:x.find(q) + 18] if q in x else -1 ## Результат print(find(letters_amazon, 'SQL'))
Попробуйте догадаться, какими будут результаты выполнения этого фрагмента кода.
Мы описали лямбда-функцию с двумя аргументами: строковым значением x и строкой запроса q, которую мы будем искать в тексте. Эту лямбда-функцию мы присваиваем переменной с именем find. Функция find(x, q) ищет строку запроса q в строке текста x.
Если поисковый запрос q не встречается в строковом значении x, мы возвращаем результат -1. В противном случае вырезаем из строки текста первое вхождение поискового запроса плюс 18 символов слева и 18 символов справа в качестве окружения запроса. Индекс первого вхождения q в x мы находим с помощью строкового метода x.find(q), который вызываем дважды: чтобы определить индекс начала и индекс конца среза, но оба вызова возвращают одно значение, поскольку ни запрос q, ни строковое значение x не меняются.
И хотя этот код прекрасно работает, избыточный вызов функции требует дополнительных вычислительных ресурсов - недостаток, который можно легко исправить, прибегнув к добавлению вспомогательной переменной для хранения результата первого вызова этой функции и обращению к значению данной переменной в дальнейшем в целях повторного использования этого результата.
Это обсуждение проливает свет на немаловажный компромисс: ограничивая себя одной строкой кода, мы лишаемся возможности описать и повторно использовать вспомогательную переменную для хранения индекса первого вхождения поискового запроса. Вместо этого нам приходится выполнять один и тот же метод find() для вычисления индекса начала среза (и уменьшить результат на 18 позиций индекса) и индекса конца среза (и увеличить результат на 18 позиций индекса). Далее мы познакомимся с более эффективном способом поиска паттернов в строках текста (с помощью регулярных выражений), позволяющем решить эту проблему.
При поиске строки символов 'SQL' в письме Amazon к акционерам мы находим следующее вхождение поискового запроса в тексте:
## Результат print(find(letters_amazon, 'SQL')) # a fully-managed MySQL and PostgreSQL
В результате получаем искомую строку символов и несколько слов около нее в качестве контекста. Срезы - важнейший элемент базового образования разработчика на языке Python. Давайте рассмотрим еще один пример однострочника.
На следующем шаге мы рассмотрим сочетание спискового включения и срезов.