На этом шаге мы рассмотрим алгоритм решения этой задачи.
Научимся проверять правильность формата вводимых пользователем данных. Пусть вы пишете веб-приложение, вычисляющее медицинские показатели на
основе длительности сна пользователей. Они вводят время отхода ко сну и время пробуждения. Пример времени в правильном формате - 12:45, но из-за спама
от веб-ботов большое количество испорченных данных приводит к излишней вычислительной нагрузке на сервер. Для решения этой проблемы вы хотите
написать средство проверки формата времени, которое бы определяло, имеет ли смысл дальнейшая обработка ваших входных данных приложением,
расположенным в прикладной части. Написание такого кода с помощью регулярных выражений занимает всего несколько минут.
В предыдущих нескольких шагах вы узнали про функции re.match(), re.search() и re.findall(). Они не единственные функции для работы с регулярными выражениями. На этом шаге мы воспользуемся функцией re.fullmatch(регулярное_выраженuе, строковое_значение), проверяющей, соответствует ли регулярному выражению полное строковое_значение, как можно предположить из ее названия.
Кроме того, мы воспользуемся синтаксисом <шаблон>{m,n} регулярных выражений, применяемым для поиска строки символов, включающей от m до n копий шаблон, но не более и не менее данного количества. Обратите внимание, что при этом производится попытка найти строку символов с максимальным количеством вхождений <шаблон>. Ниже представлен пример:
import re print(re.findall('x{3,5}y', 'xy')) # [] print(re.findall('x{3,5}y', 'xxxy')) # ['xxxy'] print(re.findall('x{3,5}y', 'xxxxxy')) # ['xxxxxy'] print(re.findall('x{3,5}y', 'xxxxxxy')) # ['xxxxxy']
При использовании нотации с фигурными скобками код не ищет соответствий подстрок, включающих менее трех и более пяти символов 'x'.
Наша задача - написать функцию input_ok, принимающую строковый аргумент и проверяющий его на соответствие формату (времени) XX:XX, где X - число от 0 до 9 (пример 5.6). Учтите, что пока мы не отбрасываем семантически неправильные форматы времени наподобие 12:86. Этой более сложной задачей мы займемся на следующем шаге.
## Зависимости import re ## Данные inputs = ['18:29', '23:55', '123', 'ab:de', '18:299', '99:99'] ## Однострочник input_ok = lambda x: re.fullmatch('[0-9]{2}:[0-9]{2}', x) != None ## Результат for x in inputs: print(input_ok(x))
Прежде чем продолжить чтение, попробуйте определить результаты шести вызовов функций в этом коде.
Наши данные состоят из шести входных строковых значений, получаемых клиентской частью веб-приложения. Правильного ли они формата? Чтобы проверить, мы создаем функцию input_ok с помощью лямбда-выражения с одним входным аргументом x и булевым выходным значением. Далее с помощью функции fullmatch(регулярное_выраженuе, x) мы пытаемся установить соответствие входному аргументу x нашему регулярному выражению для формата времени. Если это не удается, то результат принимает значение None, а булев выходной результат функции - False. В противном случае булев результат функции будет True.
Само регулярное выражение очень простое: [0-9]{2}: [0-9]{2}. Ему соответствуют два числа от 0 до 9, за которыми следует двоеточие :, за которым следуют еще два числа от 0 до 9. Таким образом, результат примера 5.6 выглядит следующим образом:
## Результат for x in inputs: print(input_ok(x)) # True # True # False # False # False # True
Функция input_ok корректно находит правильно отформатированные значения времени в inputs. В этом однострочнике показано, как часто встречающиеся на практике задачи, которые в противном случае потребовали бы больших усилий и многих строк кода, можно выполнить за несколько секунд с помощью правильного набора инструментов.
На следующем шаге мы закончим изучение этого вопроса.