Самый простой способ сделать это - поместить input
метод в цикл while. Используйте, continue
когда вы получаете плохой ввод и break
выход из цикла, когда вы удовлетворены.
Когда ваш вклад может вызвать исключение
Используйте try
и,except
чтобы определить, когда пользователь вводит данные, которые не могут быть проанализированы.
while True:
try:
# Note: Python 2.x users should use raw_input, the equivalent of 3.x's input
age = int(input("Please enter your age: "))
except ValueError:
print("Sorry, I didn't understand that.")
#better try again... Return to the start of the loop
continue
else:
#age was successfully parsed!
#we're ready to exit the loop.
break
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
Реализация ваших собственных правил валидации
Если вы хотите отклонить значения, которые Python может успешно проанализировать, вы можете добавить свою собственную логику проверки.
while True:
data = input("Please enter a loud message (must be all caps): ")
if not data.isupper():
print("Sorry, your response was not loud enough.")
continue
else:
#we're happy with the value given.
#we're ready to exit the loop.
break
while True:
data = input("Pick an answer from A to D:")
if data.lower() not in ('a', 'b', 'c', 'd'):
print("Not an appropriate choice.")
else:
break
Объединение обработки исключений и пользовательской проверки
Оба вышеуказанных метода могут быть объединены в один цикл.
while True:
try:
age = int(input("Please enter your age: "))
except ValueError:
print("Sorry, I didn't understand that.")
continue
if age < 0:
print("Sorry, your response must not be negative.")
continue
else:
#age was successfully parsed, and we're happy with its value.
#we're ready to exit the loop.
break
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
Инкапсуляция всего этого в функции
Если вам нужно запросить у пользователя много разных значений, может быть полезно поместить этот код в функцию, чтобы вам не приходилось каждый раз вводить его заново.
def get_non_negative_int(prompt):
while True:
try:
value = int(input(prompt))
except ValueError:
print("Sorry, I didn't understand that.")
continue
if value < 0:
print("Sorry, your response must not be negative.")
continue
else:
break
return value
age = get_non_negative_int("Please enter your age: ")
kids = get_non_negative_int("Please enter the number of children you have: ")
salary = get_non_negative_int("Please enter your yearly earnings, in dollars: ")
Собираем все вместе
Вы можете расширить эту идею, чтобы сделать очень общую функцию ввода:
def sanitised_input(prompt, type_=None, min_=None, max_=None, range_=None):
if min_ is not None and max_ is not None and max_ < min_:
raise ValueError("min_ must be less than or equal to max_.")
while True:
ui = input(prompt)
if type_ is not None:
try:
ui = type_(ui)
except ValueError:
print("Input type must be {0}.".format(type_.__name__))
continue
if max_ is not None and ui > max_:
print("Input must be less than or equal to {0}.".format(max_))
elif min_ is not None and ui < min_:
print("Input must be greater than or equal to {0}.".format(min_))
elif range_ is not None and ui not in range_:
if isinstance(range_, range):
template = "Input must be between {0.start} and {0.stop}."
print(template.format(range_))
else:
template = "Input must be {0}."
if len(range_) == 1:
print(template.format(*range_))
else:
expected = " or ".join((
", ".join(str(x) for x in range_[:-1]),
str(range_[-1])
))
print(template.format(expected))
else:
return ui
С использованием таких как:
age = sanitised_input("Enter your age: ", int, 1, 101)
answer = sanitised_input("Enter your answer: ", str.lower, range_=('a', 'b', 'c', 'd'))
Типичные ошибки и почему их следует избегать
Избыточное использование избыточных input
заявлений
Этот метод работает, но обычно считается плохим стилем:
data = input("Please enter a loud message (must be all caps): ")
while not data.isupper():
print("Sorry, your response was not loud enough.")
data = input("Please enter a loud message (must be all caps): ")
На первый взгляд он может выглядеть привлекательно, потому что он короче while True
метода, но он нарушает принцип разработки программного обеспечения « Не повторяйся» . Это увеличивает вероятность ошибок в вашей системе. Что делать, если вы хотите сделать бэкпорт в 2.7, изменив input
на raw_input
, но случайно изменив только первый из input
приведенных выше? Это SyntaxError
просто ожидание, чтобы случиться.
Рекурсия взорвет ваш стек
Если вы только что узнали о рекурсии, у вас может возникнуть соблазн использовать ее, get_non_negative_int
чтобы вы могли избавиться от цикла while.
def get_non_negative_int(prompt):
try:
value = int(input(prompt))
except ValueError:
print("Sorry, I didn't understand that.")
return get_non_negative_int(prompt)
if value < 0:
print("Sorry, your response must not be negative.")
return get_non_negative_int(prompt)
else:
return value
В большинстве случаев это работает нормально, но если пользователь вводит неверные данные достаточно много раз, сценарий завершается с RuntimeError: maximum recursion depth exceeded
. Вы можете подумать, что «ни один дурак не сделает 1000 ошибок подряд», но вы недооцениваете изобретательность дураков!
input
цикл, и цикл станет очень коротким, но условие может стать довольно длинным ...Зачем вам делать
while True
а затем выходить из этого цикла, в то время как вы можете просто указать свои требования в операторе while, поскольку все, что вам нужно, - это остановиться после достижения возраста?Это приведет к следующему:
это будет работать, так как возраст никогда не будет иметь значения, которое не имеет смысла, а код следует логике вашего «бизнес-процесса»
источник
Хотя принятый ответ удивителен. Я также хотел бы поделиться быстрым взломом для этой проблемы. (Это также решает проблему отрицательного возраста.)
PS Этот код для Python 3.x.
источник
def
вместо этого.def f(age):
гораздо понятнееf = lambda age:
Итак, я недавно возился с чем-то похожим на это, и я придумал следующее решение, которое использует способ получения ввода, который отвергает нежелательную информацию, прежде чем она будет проверена каким-либо логическим способом.
read_single_keypress()
вежливость https://stackoverflow.com/a/6599441/4532996Вы можете найти полный модуль здесь .
Пример:
Обратите внимание, что природа этой реализации заключается в том, что она закрывает стандартный ввод, как только что-то, что не является цифрой, читается. Я не нажимал ввод после
a
, но мне нужно было после чисел.Вы можете объединить это с
thismany()
функцией в том же модуле, чтобы разрешить, скажем, только три цифры.источник
Функциональный подход или " смотри мама без петель! "
или если вы хотите, чтобы сообщение о "неверном вводе" было отделено от запроса ввода, как в других ответах:
Как это работает?
itertools.chain
иitertools.repeat
создаст итератор, который будет выдавать строки"Enter a number: "
один раз и"Not a number! Try again: "
бесконечное число раз:replies = map(input, prompts)
- здесьmap
будут применены всеprompts
строки из предыдущего шага кinput
функции. Например:filter
иstr.isdigit
для фильтрации тех строк, которые содержат только цифры: И чтобы получить только первую строку из цифр, которую мы используемnext
.Другие правила проверки:
Строковые методы: Конечно, вы можете использовать другие строковые методы, например,
str.isalpha
чтобы получать только буквенные строки илиstr.isupper
только в верхнем регистре. Смотрите документы для полного списка.Тестирование членства:
Есть несколько различных способов выполнить это. Одним из них является использование
__contains__
метода:Сравнение чисел:
есть полезные методы сравнения, которые мы можем использовать здесь. Например, для
__lt__
(<
):Или, если вам не нравится использование более сложных методов (dunder = двойное подчеркивание), вы всегда можете определить свою собственную функцию или использовать функции из
operator
модуля.Существование пути:
здесь можно использовать
pathlib
библиотеку и ееPath.exists
метод:Ограничение количества попыток:
Если вы не хотите пытать пользователя, задавая ему что-то бесконечное количество раз, вы можете указать ограничение в вызове
itertools.repeat
. Это можно сочетать с предоставлениемnext
функции значения по умолчанию :Предварительная обработка входных данных:
Иногда мы не хотим отклонять ввод, если пользователь случайно предоставил его IN CAPS или с пробелом в начале или конце строки. Для того, чтобы эти простые ошибки во внимание , мы можем препроцессировать входные данные путем применения
str.lower
иstr.strip
методы. Например, в случае тестирования членства код будет выглядеть так:В случае, когда у вас есть много функций для предварительной обработки, может быть проще использовать функцию, выполняющую композицию функций . Например, используя один из здесь :
Объединение правил проверки:
Например, для простого случая, когда программа запрашивает возраст от 1 до 120 лет, можно просто добавить еще один
filter
:Но в случае, когда существует много правил, лучше реализовать функцию, выполняющую логическое соединение . В следующем примере я буду использовать готовый отсюда :
К сожалению, если кому-то нужно индивидуальное сообщение для каждого неудачного случая, то, боюсь, не существует достаточно функционального способа. Или, по крайней мере, я не смог найти.
источник
Используя Click :
Click - это библиотека для интерфейсов командной строки, которая предоставляет функциональные возможности для запроса правильного ответа от пользователя.
Простой пример:
Обратите внимание, как он автоматически преобразовал строковое значение в число с плавающей точкой.
Проверка, находится ли значение в пределах диапазона:
Существуют различные пользовательские типы . Чтобы получить число в определенном диапазоне, мы можем использовать
IntRange
:Мы также можем указать только одно из ограничений
min
илиmax
:Тестирование членства:
Используя
click.Choice
тип. По умолчанию эта проверка чувствительна к регистру.Работа с путями и файлами:
Используя
click.Path
тип, мы можем проверить существующие пути, а также разрешить их:Чтение и запись файлов могут быть выполнены
click.File
:Другие примеры:
Подтверждение пароля:
Значения по умолчанию:
В этом случае простое нажатие Enter(или клавиша, которую вы используете) без ввода значения даст вам значение по умолчанию:
источник
источник
Опираясь на отличные предложения Дэниела Кью и Патрика Артнера, мы предлагаем еще более обобщенное решение.
Я выбрал явные
if
иraise
операторы вместоassert
, потому что проверка утверждений может быть отключена, тогда как проверка всегда должна быть включена, чтобы обеспечить надежность.Это может быть использовано для получения разных видов ввода с разными условиями проверки. Например:
Или, чтобы ответить на оригинальный вопрос:
источник
Попробуй это:-
источник
Хотя блок
try
/except
будет работать, гораздо более быстрый и чистый способ решения этой задачи будет заключаться в использованииstr.isdigit()
.источник
Хороший вопрос! Вы можете попробовать следующий код для этого. знак равно
Этот код использует ast.literal_eval (), чтобы найти тип данных input (
age
). Далее следует следующий алгоритм:Вот код
источник
Вы всегда можете применить простую логику if-else и добавить еще одну
if
логику в свой код вместе сfor
циклом.Это будет бесконечный туалет, и вас попросят ввести возраст бесконечно.
источник
Вы можете написать более общую логику, чтобы позволить пользователю вводить только определенное количество раз, поскольку один и тот же вариант использования возникает во многих реальных приложениях.
источник
Вы можете сделать оператор ввода циклом while True, чтобы он неоднократно запрашивал ввод данных пользователем, а затем прерывал этот цикл, если пользователь вводит ответ, который вы хотите. И вы можете использовать try и кроме блоков для обработки неправильных ответов.
Переменная var такова, что если пользователь введет строку вместо целого числа, программа не выдаст «Вы не можете голосовать в Соединенных Штатах».
источник
Используйте оператор while до тех пор, пока пользователь не введет истинное значение, и если входное значение не является числом или является нулевым значением, пропустите его и попробуйте снова спросить и так далее. В примере я попытался ответить на ваш вопрос по-настоящему. Если мы предположим, что наш возраст составляет от 1 до 150, то входное значение будет принято, иначе это неправильное значение. Для завершения программы пользователь может использовать клавишу 0 и ввести ее в качестве значения.
источник
Еще одно решение для использования проверки входных данных с использованием настраиваемой
ValidationError
и (необязательной) проверки диапазона для целочисленных входных данных:Применение:
Вывод:
источник
Вот более чистое, более обобщенное решение, которое позволяет избежать повторяющихся блоков if / else: напишите функцию, которая принимает пары (Ошибка, ошибка) в словаре и выполняет всю проверку значений с помощью утверждений.
Применение:
источник
Постоянный пользовательский ввод с использованием рекурсивной функции :
строка
целое число
и, наконец, требование вопроса:
источник
Простое решение будет:
Объяснение приведенного выше кода: для того, чтобы иметь действительный возраст, он должен быть положительным и не должен превышать нормальный физический возраст, например, максимальный возраст составляет 120 лет.
Затем мы можем запросить у пользователя возраст, а если введенный возраст отрицательный или превышает 120, мы считаем его недействительным и просим пользователя повторить попытку.
После ввода правильного ввода мы выполняем проверку (используя вложенный оператор if-else), является ли возраст> = 18 или наоборот, и печатаем сообщение о том, имеет ли пользователь право голоса
источник
принять ввод как строку и использовать isdigit (), чтобы проверить, что вход имеет только цифры, не пустой, не может быть -ve
источник