Диалоговые программы используются везде, примером может служить любое приложение на вашем компьютере (браузер, видеоплееры, текстовые редакторы и т. д.). Диалог Yes/No — это простой пример диалоговой программы, работающей с командной строкой.
Что такое диалоговая программа и зачем она нужна
Программа, в которой предусмотрено взаимодействие с пользователем, называется диалоговой (интерактивной).
Ввод текста, нажатия на кнопки, загрузка файлов — всё это способы взаимодействия пользователя с приложением.
Диалог между программой и пользователем — это важная часть любого проекта. Если программа работает с одними строго определенными данными, она не несёт какого-либо практического смысла.
Диалоговая программа Yes/No на Python
Диалог может вестись как через графический интерфейс, так и через командную строку. С помощью Python можно реализовать и то и другое, однако общение с пользователем через терминал имеет более простую реализацию и требует меньше кода.
Суть такой программы проста: пользователь отвечает на вопросы, вводя в консоль Yes – да, или No – нет. Не стоит думать, что сейчас актуально взаимодействовать с программой только через графический интерфейс, командная строка также используется.
Понятно, что диалог через командную строку чаще используется продвинутыми пользователями или техническими специалистами, которых не пугает работа в режиме текстовых команд.
Консольный диалог Yes/No особенно актуален, потому что не требует реализовывать графический интерфейс, который может быть бесполезен для выполнения определённых задач.
Реализация функции диалога Yes/No на Python
Написать консольную диалоговую программу на Python очень просто, однако нужно учесть и продумать некоторые нюансы, такие как неверный ввод от пользователя. Yes/no легко можно заменить на Да/нет, но давайте следовать общепринятым стандартам и использовать английский язык.
Объявление функции
Поместим всю логику диалоговой программы в отдельную функцию, которую объявим так:
def yes_no_dialog(question, default_answer="yes"):
Здесь аргументы означают следующее:
question
– это вопрос, который выводится в командную строку, и на который пользователь должен дать ответ «yes» или «no».default_ answer
– это необязательный параметр, который будет использоваться в том случае, если пользователь не введет ответ, а просто нажмет Enter.
Начальные настройки
Предположим, что пользователь может вводить не только «yes», но и «y» или «ye». Обработка каждого вариант с помощью условных операторов if — else нецелесообразна и требует много лишнего кода. Поэтому поместим все варианты ответа в словарь:
answers = {"yes":1, "y":1, "ye":1, "no":0, "n":0}
default_answer
позволяет указать предпочтительный вариант ответа, однако это не очевидно для обычного пользователя. В зависимости от содержимого default_answer
будем выводить соответствующую подсказку:
if default_answer == None: # Если ответ по умолчанию не определен tip = " [y/n] " # выводим обе буквы в нижнем регистре elif default_answer == "yes": # Если ответ по умолчанию "yes" tip = " [Y/n] " # Выделяем Y elif default_answer == "no": # Если ответ по умолчанию "no" tip = " [y/N] " else: raise ValueError(f'Неверное значение: {default_answer = }')
При вводе аргумента default_answer
тоже можно допустить ошибку, поэтому в блоке else
мы возбуждаем исключение, которое указывает на неверный ввод.
Основной цикл
Необходимо продумать следующие ситуации, когда пользователь:
- Ничего не вводит, но определен
default_answer
. - Вводит верный ответ.
- Вводит неверный ответ.
Для реализации лучше использовать бесконечный цикл. Сначала необходимо вывести вопрос и подсказку, а затем получить ввод пользователя:
while True: print(question + tip + ": ", end="") user_answer = input().lower() # приводим к нижнему регистру
Подробнее про ввод и вывод данных можно почитать здесь.
Теперь ввод необходимо обработать так, чтобы при правильном вводе происходил выход из цикла, а при неправильном цикл начинался заново:
# Если default_answer определен, а пользователь ничего не ввёл if default_answer is not None and user_answer == '': # Выходим из функции, возвращая значение, соответствующее default_answer return answers[default_answer] # Если пользователь ввел верный ответ elif user_answer in answers: return answers[user_answer] # Если ответ неверен, выводим сообщение и продолжаем цикл else: print("Пожалуйста, введите yes/y или no/n\n")
Полный код функции
Соединив все вместе, получаем готовую к использованию функцию для диалога с пользователем:
def yes_no_dialog(question, default_answer="yes"): answers = {"yes":1, "y":1, "ye":1, "no":0, "n":0} if default_answer == None: tip = " [y/n] " elif default_answer == "yes": tip = " [Y/n] " elif default_answer == "no": tip = " [y/N] " else: raise ValueError(f'Неверное значение: {default_answer = }') while True: print(question + tip + ": ", end="") user_answer = input().lower() if default_answer is not None and user_answer == '': return answers[default_answer] elif user_answer in answers: return answers[user_answer] else: print("Пожалуйста, введите yes/y или no/n\n")
Пример программы
Предположим, что функция получает несколько вопросов из файла, результаты ответов записываются в другой файл, тогда код программы будет выглядеть так:
a = open("qst.txt", "r", encoding="utf-8") # открываем файл для чтения results = [] for line in a: # читаем файл построчно # Для каждой строки вызываем нашу функцию и помещаем возвращаемое # ею значение в список result results.append(yes_no_dialog(line.strip())) a.close() b = open("results.txt", "w") # Открываем файл для записи for elem in results: # Записываем каждый элемент списка в файл через пробел b.write(str(elem) + " ") b.close()
С помощью метода строк strip удалим лишние символы.
Перед запуском программы на Python надо не забыть подготовить файл с вопросами qst.txt такого вида:
Первый вопрос Второй вопрос Третий вопрос
Чтобы русские буквы корректно отображались — правильно указываем кодировку при открытии файла. В моём случае это encoding="utf-8"
.
Результатом выполнения будет следующее:
Первый вопрос [Y/n] : Y Второй вопрос [Y/n] : no Третий вопрос [Y/n] : yes
Содержимое файла результата будет следующим:
1 0 1