Python: Мислення програміста

Невелика стаття про те, як можна вирішити ту ж задачу кількома способами. Призначена для новачків в Python і програмуванні.
В якості прикладу взято простий випадок — реалізація діалогу підтвердження якої-небудь операції. Програма задає користувачеві питання
Ви впевнені? [Д/н (Y/n)]:
, на який потрібно відповісти, ввівши одне з восьми допустимих значень (
Д
,
д
,
Н
,
н
,
Y
,
y
,
N
,
n
).
Спосіб №1
Перше, що приходить на розум, це реалізувати перевірку збігу кожного з умов наступним чином:
#!/usr/bin/python env
# -*- 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/python env
# -*- 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/python env
# -*- 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/python env
# -*- coding: utf-8 -*-

import re # Імпорт модуля для роботи з регулярними виразами

def are_you_sure4():
while True:
print("Ви впевнені? [Д/н (Y/n)]: ")
response = input()

if re.match("[уУдД]", response):
print("Позитивний відповідь: {}".format(response))
elif re.match("[nNнН]", response):
print("Негативну відповідь: {}".format(response))
else:
print("Введено некоректну значення: {}".format(response))

are_you_sure4()

Метод
re.match(шаблон, рядок)
шукає по заданому шаблону на початку рядка. В якості шаблону використовується регулярний вираз
[уУдД]
та
[nNнН]
(квадратні дужки групують символи). Більш детально тема регулярних виразів розкривається в статтях, посилання на які наведено в кінці. Також рекомендую книгу «Освой самостійно регулярні вирази. 10 хвилин на урок» Бена Форти.
У цьому способі теж можна використовувати принцип відсікання зайвого і скоротити регулярні вирази до виду
[УД]
та
[NН]
з допомогою методу
upper()
.
Також варто відзначити, що в даному випадку коректними будуть вважатися будь-які значення, що починаються з дозволених символів, наприклад,
та
,
Yum
і т. д., так як
re.match()
шукає збіги тільки з початку рядка. На відміну від інших способів, де повинно бути точне відповідність і будь-які зайві символи викличуть повідомлення про некоректність. Можна вважати це перевагою, але нічого не заважає виправити таку поведінку.
Останній спосіб зайвий для такого простого прикладу, але хороший своєю універсальністю і розширюваністю, так як регулярні вирази дозволяють здійснювати більш складну перевірку (наприклад, перевірку e-mail).
Спосіб №5
В коментарях random1st навів ще один витончений спосіб:
#!/usr/bin/python env
# -*- coding: utf-8 -*-

def check_answer():
while True:
response = input('Ви впевнені? [Д/н (Y/n)]: ')
try:
print( 0 <= "YyДдNnНн".index(response) <=3 and "True" або "False")
except ValueError:
print ("Incorrect")

check_answer()

І як справедливо зауважив saboteur_kiev, цей спосіб витончений, але не дуже гарний з точки зору підтримки коду. Якщо потрібно додавати нові значення буде інший розробник — воно читається і розуміється гірше, ніж рішення з попереднього коментаря, де позитивний і негативний відповідь явно розділені.
Ремарка
@datacompboy і MamOn вказали на ще один цікавий момент. Символ
Y
та
Н
на російськомовній клавіатурі знаходяться на одній кнопці, що при неуважності з боку користувача може привести до абсолютно протилежних результатів. Подібні моменти теж потрібно враховувати при розробці. Тому в додатках, де помилка вибору може призвести до незворотних результатами, краще зажадати підтвердження
Yes
/
No
, щоб напевно виключити можливість помилки.
Посилання
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.