Python: Мышление программиста
Небольшая статья о том, как можно решить одну и ту же задачу несколькими способами. Предназначена для новичков в Python и программировании.
В качестве примера взят простой случай — реализация диалога подтверждения какой-либо операции. Программа задает пользователю вопрос
Вы уверены? [Д/н (Y/n)]:
, на который требуется ответить, введя одно из восьми допустимых значений (Д, д, Н, н, Y, y, N, n
).Способ №1
Первое, что приходит на ум, это реализовать проверку совпадения каждого из условий следующим образом:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def are_you_sure1():
while True:
print("Вы уверены? [Д/н (Y/n)]: ")
response = input()
if response == "Д" or response == "д":
print("Положительный ответ: {}".format(response))
elif response == "Y" or response == "y":
print("Положительный ответ: {}".format(response))
elif response == "Н" or response == "н":
print("Отрицательный ответ: {}".format(response))
elif response == "N" or response == "n":
print("Отрицательный ответ: {}".format(response))
else:
print("Введено некорректное значение: {}".format(response)
are_you_sure1()
Можно было расписать все 8 блоков
if/elif
, но для краткости используется логический оператор or
(ИЛИ) для каждой из пар возможных значений.В этом решении нет ничего плохого и оно является правильным, хорошо характеризуя принцип «Чем проще, тем лучше». Именно к такому решению приходит большинство начинающих питонистов.
Однако, это противоречит принципу «Не повторяйся», так как любой программист стремится к уменьшению числа вводимых символов.
Способ №2
Второй способ заключается в отсечении лишних сущностей (Бритва Оккама). Не имеет значения в каком именно регистре будет введен символ в ответ на вопрос программы. Поэтому воспользуемся методом строкиupper()
или lower()
для приведения символов к верхнему или нижнему регистру:#!/usr/bin/env python
# -*- coding: utf-8 -*-
def are_you_sure2():
while True:
print("Вы уверены? [Д/н (Y/n)]: ")
# Принимает значение, введенное пользователем и
# переводит его в верхний регистр
response = input().upper()
if response == "Д" or response == "Y":
print("Положительный ответ: {}".format(response))
elif response == "Н" or response == "N":
print("Отрицательный ответ: {}".format(response))
else:
print("Введено некорректное значение: {}".format(response))
are_you_sure2()
Введенное пользователем значение сразу же приводится к одному регистру, а далее уже происходит его проверка. Как итог — сокращение количества вводимых символов и повторяющихся блоков кода.
Способ №3
Еще один способ — проверить входит ли введенное значение в список допустимых.#!/usr/bin/env python
# -*- coding: utf-8 -*-
def are_you_sure3():
while True:
print("Вы уверены? [Д/н (Y/n)]: ")
response = input()
if response in ["Д", "д", "Y", "y"]:
print("Положительный ответ: {}".format(response))
elif response in ["Н", "н", "N", "n"]:
print("Отрицательный ответ: {}".format(response))
else:
print("Введено некорректное значение: {}".format(response))
are_you_sure3()
Проверка осуществляется с помощью оператора вхождения
in
. Пример альтернативного мышления.Способ №4
Еще один пример альтернативного мышления, заключающийся в использовании регулярных выражений. Для этого воспользуемся стандартным модулем для работы с регулярными выражениямиre
и методом re.match()
.#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re # Импорт модуля для работы с регулярными выражениями
def are_you_sure4():
while True:
print("Вы уверены? [Д/н (Y/n)]: ")
response = input()
if re.match("[yYдД]", response):
print("Положительный ответ: {}".format(response))
elif re.match("[nNнН]", response):
print("Отрицательный ответ: {}".format(response))
else:
print("Введено некорректное значение: {}".format(response))
are_you_sure4()
Метод
re.match(шаблон, строка)
ищет по заданному шаблону в начале строки. В качестве шаблона используется регулярное выражение [yYдД]
и [nNнН]
(квадратные скобки группируют символы). Более подробно тема регулярных выражений раскрывается в статьях, ссылки на которые приведены в конце. Также рекомендую книгу «Освой самостоятельно регулярные выражения. 10 минут на урок» Бена Форты.В этом способе тоже можно использовать принцип отсечения лишнего и сократить регулярные выражения до вида
[YД]
и [NН]
с помощью метода upper()
.Также стоит отметить, что в данном случае корректными будут считаться любые значения, начинающиеся с разрешенных символов, например,
да
, Yum
и т.д., так как re.match()
ищет совпадения только с начала строки. В отличии от других способов, где должно быть точное соответствие и любые лишние символы вызовут сообщение о некорректности. Можно считать это преимуществом, но ничего не мешает исправить такое поведение.Последний способ излишен для такого простого примера, но хорош своей универсальностью и расширяемостью, так как регулярные выражения позволяют осуществлять более сложную проверку (например, проверку e-mail).
Способ №5
Еще один изящный способ:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def check_answer():
while True:
response = input('Вы уверены? [Д/н (Y/n)]: ')
try:
print( 0 <= "YyДдNnНн".index(response) <=3 and "True" or "False")
except ValueError:
print ("Incorrect")
check_answer()
Этот способ изящен, но не очень красив с точки зрения поддержки кода. Если нужно добавлять новые значения будет другой разработчик — оно читается и разбирается хуже, чем решение, где позитивный и негативный ответ явно разделены:
while True:
response = input('Вы уверены? [Д/н (Y/n)]: ')
msgs = {
'yYдД': 'Положительный ответ',
'nNнН': 'Отрицательный ответ',
}
defalut = 'Введено некорректное значение'
msg = next((v for k, v in msgs.items() if response in k), defalut)
print('{}: {}'.format(msg, response))
Ремарка
Еще один интересный момент. СимволY
и Н
на русскоязычной клавиатуре находятся на одной кнопке, что при невнимательности со стороны пользователя может привести к совершенно противоположным результатам. Подобные моменты тоже нужно учитывать при разработке. Поэтому в приложениях, где ошибка выбора может привести к необратимым результатам, лучше затребовать подтверждение Yes/ No
, чтобы наверняка исключить возможность ошибки.Ссылки
- «Чем хуже, тем лучше»
- «Не повторяйся»
- Бритва Оккама
- Pythonicway: Операторы в Python
- Pythonz.net: Метод str.upper
- Бен Форта «Освой самостоятельно регулярные выражения. 10 минут на урок»
- Типичный программист: Использование регулярных выражений в Python для новичков
- Регулярные выражения в Python: изучение и оптимизация
- Хабрахабр: Регулярные выражения, пособие для новичков
Источник: Habrahabr
Комментарии - 0