Запрашиваемая у пользователя для ввода, пока они не дают действительный ответ
Я пишу программу, которая должна принимать входные данные от пользователя.
#note: Python 2.7 users should use `raw_input`, the equivalent of 3.X's `input`
age = int(input("Please enter your age: "))
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.")
Это работает, как и ожидалось, если пользователь вводит разумные данные.
C:\Python\Projects> canyouvote.py
Please enter your age: 23
You are able to vote in the United States!
Но если они ошибаются, то это вылетает:
C:\Python\Projects> canyouvote.py
Please enter your age: dickety six
Traceback (most recent call last):
File "canyouvote.py", line 1, in <module>
age = int(input("Please enter your age: "))
ValueError: invalid literal for int() with base 10: 'dickety six'
Вместо сбоя, я бы хотел, чтобы он снова попытался получить ввод. Как это:
C:\Python\Projects> canyouvote.py
Please enter your age: dickety six
Sorry, I didn't understand that.
Please enter your age: 26
You are able to vote in the United States!
Как я могу сделать это? Что делать, если я также хотел отклонить такие значения, как -1
, который является действительным int
, но бессмысленно в этом контексте?
28 ответов
Самый простой способ сделать это - поместить input
метод во время цикла. использование continue
когда вы получаете плохой ввод, и break
не в курсе, когда вы удовлетворены.
Когда ваш вклад может вызвать исключение
Используйте команду try and catch, чтобы определить, когда пользователь вводит данные, которые невозможно проанализировать.
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:
print(template.format(" or ".join((", ".join(map(str,
range_[:-1])),
str(range_[-1])))))
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 ошибок подряд", но вы недооцениваете изобретательность дураков!
Зачем тебе делать while True
и затем вырвитесь из этого цикла, в то время как вы можете просто указать свои требования в операторе while, поскольку все, что вам нужно, - это остановиться, когда вы достигнете возраста?
age = None
while age is None:
input_value = input("Please enter your age: ")
try:
# try and convert the string input to a number
age = int(input_value)
except ValueError:
# tell the user off
print("{input} is not a number, please enter a number only".format(input=input_value))
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.")
Это приведет к следующему:
Please enter your age: *potato*
potato is not a number, please enter a number only
Please enter your age: *5*
You are not able to vote in the United States.
это будет работать, так как возраст никогда не будет иметь значения, которое не будет иметь смысла, а код будет следовать логике вашего "бизнес-процесса"
Функциональный подход или " смотри мама без петель! "
from itertools import chain, repeat
prompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
replies = map(input, prompts)
valid_response = next(filter(str.isdigit, replies))
print(valid_response)
Enter a number: a
Not a number! Try again: b
Not a number! Try again: 1
1
или если вы хотите, чтобы сообщение о "неверном вводе" было отделено от запроса ввода, как в других ответах:
prompt_msg = "Enter a number: "
bad_input_msg = "Sorry, I didn't understand that."
prompts = chain([prompt_msg], repeat('\n'.join([bad_input_msg, prompt_msg])))
replies = map(input, prompts)
valid_response = next(filter(str.isdigit, replies))
print(valid_response)
Enter a number: a
Sorry, I didn't understand that.
Enter a number: b
Sorry, I didn't understand that.
Enter a number: 1
1
Как это работает?
Это сочетаниеprompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
itertools.chain
а такжеitertools.repeat
создаст итератор, который будет выдавать строки"Enter a number: "
один раз и"Not a number! Try again: "
бесконечное количество раз:for prompt in prompts: print(prompt)
Enter a number: Not a number! Try again: Not a number! Try again: Not a number! Try again: # ... and so on
replies = map(input, prompts)
- Вотmap
будет применять всеprompts
строки из предыдущего шага кinput
функция. Например:for reply in replies: print(reply)
Enter a number: a a Not a number! Try again: 1 1 Not a number! Try again: it doesn't care now it doesn't care now # and so on...
- Мы используем
filter
а такжеstr.isdigit
отфильтровать те строки, которые содержат только цифры:only_digits = filter(str.isdigit, replies) for reply in only_digits: print(reply)
И чтобы получить только первую строку только для цифр мы используемEnter a number: a Not a number! Try again: 1 1 Not a number! Try again: 2 2 Not a number! Try again: b Not a number! Try again: # and so on...
next
,
Другие правила проверки:
Строковые методы: Конечно, вы можете использовать другие строковые методы, такие как
str.isalpha
чтобы получить только буквенные строки, илиstr.isupper
чтобы получить только прописные буквы. Смотрите документы для полного списка.Тестирование членства:
Есть несколько разных способов сделать это. Одним из них является использование__contains__
метод:from itertools import chain, repeat fruits = {'apple', 'orange', 'peach'} prompts = chain(["Enter a fruit: "], repeat("I don't know this one! Try again: ")) replies = map(input, prompts) valid_response = next(filter(fruits.__contains__, replies)) print(valid_response)
Enter a fruit: 1 I don't know this one! Try again: foo I don't know this one! Try again: apple apple
Сравнение чисел:
Есть полезные методы сравнения, которые мы можем использовать здесь. Например, для__lt__
(<
):from itertools import chain, repeat prompts = chain(["Enter a positive number:"], repeat("I need a positive number! Try again:")) replies = map(input, prompts) numeric_strings = filter(str.isnumeric, replies) numbers = map(float, numeric_strings) is_positive = (0.).__lt__ valid_response = next(filter(is_positive, numbers)) print(valid_response)
Enter a positive number: a I need a positive number! Try again: -5 I need a positive number! Try again: 0 I need a positive number! Try again: 5 5.0
Или, если вам это не нравится, вы всегда можете определить свои собственные функции, или использовать те из
operator
модуль.Путь существования:
Здесь можно использоватьpathlib
библиотека и ееPath.exists
метод:from itertools import chain, repeat from pathlib import Path prompts = chain(["Enter a path: "], repeat("This path doesn't exist! Try again: ")) replies = map(input, prompts) paths = map(Path, replies) valid_response = next(filter(Path.exists, paths)) print(valid_response)
Enter a path: a b c This path doesn't exist! Try again: 1 This path doesn't exist! Try again: existing_file.txt existing_file.txt
Ограничение количества попыток:
Если вы не хотите пытать пользователя, задавая ему что-то бесконечное количество раз, вы можете указать ограничение в вызове itertools.repeat
, Это может быть объединено с предоставлением значения по умолчанию для next
функция:
from itertools import chain, repeat
prompts = chain(["Enter a number:"], repeat("Not a number! Try again:", 2))
replies = map(input, prompts)
valid_response = next(filter(str.isdigit, replies), None)
print("You've failed miserably!" if valid_response is None else 'Well done!')
Enter a number: a
Not a number! Try again: b
Not a number! Try again: c
You've failed miserably!
Объединение правил проверки:
Например, для простого случая, когда программа запрашивает возраст от 1 до 120 лет, можно просто добавить другой filter
:
from itertools import chain, repeat
prompt_msg = "Enter your age (1-120): "
bad_input_msg = "Wrong input."
prompts = chain([prompt_msg], repeat('\n'.join([bad_input_msg, prompt_msg])))
replies = map(input, prompts)
numeric_replies = filter(str.isdigit, replies)
ages = map(int, numeric_replies)
positive_ages = filter((0).__lt__, ages)
not_too_big_ages = filter((120).__ge__, positive_ages)
valid_response = next(not_too_big_ages)
print(valid_response)
Но в случае, когда существует много правил, лучше реализовать функцию, выполняющую логическое соединение. В следующем примере я буду использовать готовый отсюда:
from functools import partial
from itertools import chain, repeat
from lz.logical import conjoin
def is_one_letter(string: str) -> bool:
return len(string) == 1
rules = [str.isalpha, str.isupper, is_one_letter, 'C'.__le__, 'P'.__ge__]
prompt_msg = "Enter a letter (C-P): "
bad_input_msg = "Wrong input."
prompts = chain([prompt_msg], repeat('\n'.join([bad_input_msg, prompt_msg])))
replies = map(input, prompts)
valid_response = next(filter(conjoin(*rules), replies))
print(valid_response)
Enter a letter (C-P): 5
Wrong input.
Enter a letter (C-P): f
Wrong input.
Enter a letter (C-P): CDE
Wrong input.
Enter a letter (C-P): Q
Wrong input.
Enter a letter (C-P): N
N
К сожалению, если кому-то нужно индивидуальное сообщение для каждого неудачного случая, то, боюсь, не существует достаточно функционального способа. Или, по крайней мере, я не смог найти.
Хотя принятый ответ удивителен. Я также хотел бы поделиться быстрым взломом для этой проблемы. (Это также решает проблему отрицательного возраста.)
f=lambda age: (age.isdigit() and ((int(age)>=18 and "Can vote" ) or "Cannot vote")) or \
f(raw_input("invalid input. Try again\nPlease enter your age: "))
print f(raw_input("Please enter your age: "))
PS Этот код предназначен для Python 2.x и может быть экспортирован в 3.x путем изменения функций raw_input и print.
Используя Click:
Click - это библиотека для интерфейсов командной строки, которая предоставляет функциональные возможности для запроса правильного ответа от пользователя.
Простой пример:
number = click.prompt('Please enter a number', type=float)
print(number)
Please enter a number:
a
Error: a is not a valid floating point value
Please enter a number:
10
10.0
Обратите внимание, как он автоматически преобразовал строковое значение в число с плавающей точкой.
Проверка, находится ли значение в пределах диапазона:
Существуют различные пользовательские типы. Чтобы получить число в определенном диапазоне, мы можем использовать IntRange
:
age = click.prompt("What's your age?", type=click.IntRange(1, 120))
print(age)
What's your age?:
a
Error: a is not a valid integer
What's your age?:
0
Error: 0 is not in the valid range of 1 to 120.
What's your age?:
5
5
Мы также можем указать только одно из ограничений, min
или же max
:
age = click.prompt("What's your age?", type=click.IntRange(min=14))
print(age)
What's your age?:
0
Error: 0 is smaller than the minimum valid value 14.
What's your age?:
18
18
Тестирование членства:
С помощью click.Choice
тип. По умолчанию эта проверка чувствительна к регистру.
choices = {'apple', 'orange', 'peach'}
choice = click.prompt('Provide a fruit', type=click.Choice(choices, case_sensitive=False))
print(choice)
Provide a fruit (apple, peach, orange):
banana
Error: invalid choice: banana. (choose from apple, peach, orange)
Provide a fruit (apple, peach, orange):
OrAnGe
orange
Работа с путями и файлами:
Используя click.Path
введите, мы можем проверить существующие пути, а также разрешить их:
path = click.prompt('Provide path', type=click.Path(exists=True, resolve_path=True))
print(path)
Provide path:
nonexistent
Error: Path "nonexistent" does not exist.
Provide path:
existing_folder
'/path/to/existing_folder
Чтение и запись файлов могут быть выполнены click.File
:
file = click.prompt('In which file to write data?', type=click.File('w'))
with file.open():
file.write('Hello!')
# More info about `lazy=True` at:
# https://click.palletsprojects.com/en/7.x/arguments/#file-opening-safety
file = click.prompt('Which file you wanna read?', type=click.File(lazy=True))
with file.open():
print(file.read())
In which file to write data?:
# <-- provided an empty string, which is an illegal name for a file
In which file to write data?:
some_file.txt
Which file you wanna read?:
nonexistent.txt
Error: Could not open file: nonexistent.txt: No such file or directory
Which file you wanna read?:
some_file.txt
Hello!
Другие примеры:
Подтверждение пароля:
password = click.prompt('Enter password', hide_input=True, confirmation_prompt=True)
print(password)
Enter password:
······
Repeat for confirmation:
·
Error: the two entered values do not match
Enter password:
······
Repeat for confirmation:
······
qwerty
Значения по умолчанию:
В этом случае простое нажатие клавиши Enter (или любой другой клавиши, которую вы используете) без ввода значения даст вам значение по умолчанию:
number = click.prompt('Please enter a number', type=int, default=42)
print(number)
Please enter a number [42]:
a
Error: a is not a valid integer
Please enter a number [42]:
42
Да, я опоздал на 6 лет, но этот вопрос заслуживает более актуального ответа.
Разделение проблем
Я большой поклонник философии Unix "Делай одно и делай это хорошо". В этом типе проблемы лучше разделить проблему на
- Спросите ввод с
get_input
пока ввод не будет в порядке. - Подтвердить в
validator
функция. Вы можете написать разные валидаторы для разных входных запросов.
Просьба ввести
Его можно сохранить так же просто, как (Python 3+)
def myvalidator(value):
try:
value = int(value)
except ValueError:
return False
return value >= 0
def get_input(prompt, validator, on_validationerror):
while True:
value = input(prompt)
if validator(value):
return value
print(on_validationerror)
пример
In [2]: get_input('Give a positive number: ', myvalidator, 'Please, try again')
Give a positive number: foobar
Please, try again
Give a positive number: -10
Please, try again
Give a positive number: 42
Out[2]: '42'
Примечание Python 3.8+
В Python 3.8+ вы можете использовать оператор моржа
def get_input(prompt, validator, on_validationerror):
while not validator(value := input(prompt)):
print(on_validationerror)
return value
Итак, я недавно возился с чем-то похожим на это и придумал следующее решение, которое использует способ получения входных данных, который отклоняет ненужную информацию, еще до того, как она будет проверена каким-либо логическим способом.
read_single_keypress()
вежливость /questions/40208640/kak-zastavit-python-zhdat-nazhatoj-klavishi/40208657#40208657
def read_single_keypress() -> str:
"""Waits for a single keypress on stdin.
-- from :: https://stackru.com/a/6599441/4532996
"""
import termios, fcntl, sys, os
fd = sys.stdin.fileno()
# save old state
flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
attrs_save = termios.tcgetattr(fd)
# make raw - the way to do this comes from the termios(3) man page.
attrs = list(attrs_save) # copy the stored version to update
# iflag
attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK
| termios.ISTRIP | termios.INLCR | termios. IGNCR
| termios.ICRNL | termios.IXON )
# oflag
attrs[1] &= ~termios.OPOST
# cflag
attrs[2] &= ~(termios.CSIZE | termios. PARENB)
attrs[2] |= termios.CS8
# lflag
attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON
| termios.ISIG | termios.IEXTEN)
termios.tcsetattr(fd, termios.TCSANOW, attrs)
# turn off non-blocking
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
# read a single keystroke
try:
ret = sys.stdin.read(1) # returns a single character
except KeyboardInterrupt:
ret = 0
finally:
# restore old state
termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
return ret
def until_not_multi(chars) -> str:
"""read stdin until !(chars)"""
import sys
chars = list(chars)
y = ""
sys.stdout.flush()
while True:
i = read_single_keypress()
_ = sys.stdout.write(i)
sys.stdout.flush()
if i not in chars:
break
y += i
return y
def _can_you_vote() -> str:
"""a practical example:
test if a user can vote based purely on keypresses"""
print("can you vote? age : ", end="")
x = int("0" + until_not_multi("0123456789"))
if not x:
print("\nsorry, age can only consist of digits.")
return
print("your age is", x, "\nYou can vote!" if x >= 18 else "Sorry! you can't vote")
_can_you_vote()
Вы можете найти полный модуль здесь.
Пример:
$ ./input_constrain.py
can you vote? age : a
sorry, age can only consist of digits.
$ ./input_constrain.py
can you vote? age : 23<RETURN>
your age is 23
You can vote!
$ _
Обратите внимание, что природа этой реализации заключается в том, что она закрывает стандартный ввод, как только что-то, что не является цифрой, читается. Я не нажал ввод после a
, но мне нужно было после номера.
Вы можете объединить это с thismany()
функция в том же модуле, чтобы позволить, скажем, только три цифры.
Используйте try-except для обработки ошибки и повторите ее снова:
while True:
try:
age = int(input("Please enter your age: "))
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.")
except Exception as e:
print("please enter number")
Опираясь на отличные предложения Дэниела Кью и Патрика Артнера, мы предлагаем еще более обобщенное решение.
# Assuming Python3
import sys
class ValidationError(ValueError): # thanks Patrick Artner
pass
def validate_input(prompt, cast=str, cond=(lambda x: True), onerror=None):
if onerror==None: onerror = {}
while True:
try:
data = cast(input(prompt))
if not cond(data): raise ValidationError
return data
except tuple(onerror.keys()) as e: # thanks Daniel Q
print(onerror[type(e)], file=sys.stderr)
Я выбрал явное if
а также raise
заявления вместо assert
потому что проверка утверждений может быть отключена, тогда как проверка всегда должна быть включена, чтобы обеспечить надежность.
Это может быть использовано для получения разных видов ввода с разными условиями проверки. Например:
# No validation, equivalent to simple input:
anystr = validate_input("Enter any string: ")
# Get a string containing only letters:
letters = validate_input("Enter letters: ",
cond=str.isalpha,
onerror={ValidationError: "Only letters, please!"})
# Get a float in [0, 100]:
percentage = validate_input("Percentage? ",
cast=float, cond=lambda x: 0.0<=x<=100.0,
onerror={ValidationError: "Must be between 0 and 100!",
ValueError: "Not a number!"})
Или, чтобы ответить на оригинальный вопрос:
age = validate_input("Please enter your age: ",
cast=int, cond=lambda a:0<=a<150,
onerror={ValidationError: "Enter a plausible age, please!",
ValueError: "Enter an integer, please!"})
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 validate_age(age):
if age >=0 :
return True
return False
while True:
try:
age = int(raw_input("Please enter your age:"))
if validate_age(age): break
except ValueError:
print "Error: Invalid age."
Хороший вопрос! Вы можете попробовать следующий код для этого. знак равно
Этот код использует ast.literal_eval(), чтобы найти тип данных ввода (age
). Далее следует следующий алгоритм:
Попросить пользователя ввести ее / его
age
,1.1. Если
age
являетсяfloat
или жеint
тип данных:
Проверить, если
age>=18
, Еслиage>=18
, распечатайте соответствующий вывод и выйдите.Проверить, если
0<age<18
, Если0<age<18
, распечатайте соответствующий вывод и выйдите.Если
age<=0
попросите пользователя снова ввести действительное число для возраста (т.е. вернуться к шагу 1.)1.2. Если
age
не являетсяfloat
или жеint
тип данных, затем попросите пользователя снова ввести свой возраст (т.е. вернуться к шагу 1.)
Вот код
from ast import literal_eval
''' This function is used to identify the data type of input data.'''
def input_type(input_data):
try:
return type(literal_eval(input_data))
except (ValueError, SyntaxError):
return str
flag = True
while(flag):
age = raw_input("Please enter your age: ")
if input_type(age)==float or input_type(age)==int:
if eval(age)>=18:
print("You are able to vote in the United States!")
flag = False
elif eval(age)>0 and eval(age)<18:
print("You are not able to vote in the United States.")
flag = False
else: print("Please enter a valid number as your age.")
else: print("Sorry, I didn't understand that.")
Используйте оператор while до тех пор, пока пользователь не введет истинное значение, а если входное значение не является числом или является нулевым, пропустите его и попробуйте снова спросить и так далее. В примере я постарался верно ответить на ваш вопрос. Если мы предположим, что наш возраст составляет от 1 до 150, то входное значение будет принято, иначе это неправильное значение. Для завершения программы пользователь может использовать клавишу 0 и ввести ее в качестве значения.
Примечание. Прочитайте комментарии в начале кода.
# If your input value is only a number then use "Value.isdigit() == False".
# If you need an input that is a text, you should remove "Value.isdigit() == False".
def Input(Message):
Value = None
while Value == None or Value.isdigit() == False:
try:
Value = str(input(Message)).strip()
except InputError:
Value = None
return Value
# Example:
age = 0
# If we suppose that our age is between 1 and 150 then input value accepted,
# else it's a wrong value.
while age <=0 or age >150:
age = int(Input("Please enter your age: "))
# For terminating program, the user can use 0 key and enter it as an a value.
if age == 0:
print("Terminating ...")
exit(0)
if age >= 18 and age <=150:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
Попробуй это:-
def takeInput(required):
print 'ooo or OOO to exit'
ans = raw_input('Enter: ')
if not ans:
print "You entered nothing...!"
return takeInput(required)
## FOR Exit ##
elif ans in ['ooo', 'OOO']:
print "Closing instance."
exit()
else:
if ans.isdigit():
current = 'int'
elif set('[~!@#$%^&*()_+{}":/\']+$').intersection(ans):
current = 'other'
elif isinstance(ans,basestring):
current = 'str'
else:
current = 'none'
if required == current :
return ans
else:
return takeInput(required)
## pass the value in which type you want [str/int/special character(as other )]
print "input: ", takeInput('str')
Чтобы отредактировать свой код и исправить ошибку:
while True:
try:
age = int(input("Please enter your age: "))
if age >= 18:
print("You are able to vote in the United States!")
break
else:
print("You are not able to vote in the United States.")
break
except ValueError:
print("Please enter a valid response")
Вы можете написать более общую логику, чтобы позволить пользователю вводить только определенное количество раз, поскольку один и тот же вариант использования возникает во многих реальных приложениях.
def getValidInt(iMaxAttemps = None):
iCount = 0
while True:
# exit when maximum attempt limit has expired
if iCount != None and iCount > iMaxAttemps:
return 0 # return as default value
i = raw_input("Enter no")
try:
i = int(i)
except ValueError as e:
print "Enter valid int value"
else:
break
return i
age = getValidInt()
# do whatever you want to do.
Используйте try catch с бесконечным циклом while. Чтобы проверить наличие пустой строки, используйте оператор IF, чтобы проверить, является ли строка пустой.
while True:
name = input("Enter Your Name\n")
if not name:
print("I did not understood that")
continue
else:
break
while True:
try:
salary = float(input("whats ur salary\n"))
except ValueError:
print("I did not understood that")
continue
else:
break
while True:
try:
print("whats ur age?")
age = int(float(input()))
except ValueError:
print("I did not understood that")
continue
else:
break
print("Hello "+ name + "\nYour salary is " + str(salary) + '\nand you will be ' + str(age+1) +' in a Year')
Вот более чистое, более обобщенное решение, которое позволяет избежать повторяющихся блоков if/else: напишите функцию, которая принимает (словарь, ошибка) пары в словаре и выполняет всю проверку значений с помощью утверждений.
def validate_input(prompt, error_map):
while True:
try:
data = int(input(prompt))
# Insert your non-exception-throwing conditionals here
assert data > 0
return data
# Print whatever text you want the user to see
# depending on how they messed up
except tuple(error_map.keys()) as e:
print(error_map[type(e)])
Использование:
d = {ValueError: 'Integers only', AssertionError: 'Positive numbers only',
KeyboardInterrupt: 'You can never leave'}
user_input = validate_input("Positive number: ", d)
Вы всегда можете применить простую логику if-else и добавить еще один if
логики вашего кода вместе с for
петля.
while True:
age = int(input("Please enter your age: "))
if (age >= 18) :
print("You are able to vote in the United States!")
if (age < 18) & (age > 0):
print("You are not able to vote in the United States.")
else:
print("Wrong characters, the input must be numeric")
continue
Это будет бесконечный цикл, и вас попросят ввести возраст на неопределенный срок.
При этом пользователь будет продолжать вводить номер, пока не введет действительное число:
#note: Python 2.7 users should use raw_input, the equivalent of 3.X's input
while(1):
try:
age = int(input("Please enter your age: "))
if age >= 18:
print("You are able to vote in the United States!")
break()
else:
print("You are not able to vote in the United States.")
break()
except:
print("Please only enter numbers ")
В то время как try
/except
блок будет работать, гораздо более быстрый и чистый способ решения этой задачи будет использовать str.isdigit()
,
while True:
age = input("Please enter your age: ")
if age.isdigit():
age = int(age)
break
else:
print("Invalid number '{age}'. Try again.".format(age=age))
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 askName():
return input("Write your name: ").strip() or askName()
name = askName()
целое число
def askAge():
try: return int(input("Enter your age: "))
except ValueError: return askAge()
age = askAge()
и, наконец, требование вопроса:
def askAge():
try: return int(input("Enter your age: "))
except ValueError: return askAge()
age = askAge()
responseAge = [
"You are able to vote in the United States!",
"You are not able to vote in the United States.",
][int(age < 18)]
print(responseAge)
Вы можете сделать оператор ввода циклом True, чтобы он постоянно запрашивал ввод данных пользователем, а затем прерывал этот цикл, если пользователь вводит ответ, который вы хотите. И вы можете использовать try и кроме блоков для обработки неправильных ответов.
while True:
var = True
try:
age = int(input("Please enter your age: "))
except ValueError:
print("Invalid input.")
var = False
if var == True:
if age >= 18:
print("You are able to vote in the United States.")
break
else:
print("You are not able to vote in the United States.")
Переменная var такова, что если пользователь введет строку вместо целого числа, программа не выдаст "Вы не можете голосовать в Соединенных Штатах".
Еще одно решение для использования проверки ввода с использованием настроенного ValidationError
и (необязательно) проверка диапазона для целочисленных входных данных:
class ValidationError(ValueError):
"""Special validation error - its message is supposed to be printed"""
pass
def RangeValidator(text,num,r):
"""Generic validator - raises 'text' as ValidationError if 'num' not in range 'r'."""
if num in r:
return num
raise ValidationError(text)
def ValidCol(c):
"""Specialized column validator providing text and range."""
return RangeValidator("Columns must be in the range of 0 to 3 (inclusive)",
c, range(4))
def ValidRow(r):
"""Specialized row validator providing text and range."""
return RangeValidator("Rows must be in the range of 5 to 15(exclusive)",
r, range(5,15))
Использование:
def GetInt(text, validator=None):
"""Aks user for integer input until a valid integer is given. If provided,
a 'validator' function takes the integer and either raises a
ValidationError to be printed or returns the valid number.
Non integers display a simple error message."""
print()
while True:
n = input(text)
try:
n = int(n)
return n if validator is None else validator(n)
except ValueError as ve:
# prints ValidationErrors directly - else generic message:
if isinstance(ve, ValidationError):
print(ve)
else:
print("Invalid input: ", n)
column = GetInt("Pleased enter column: ", ValidCol)
row = GetInt("Pleased enter row: ", ValidRow)
print( row, column)
Выход:
Pleased enter column: 22
Columns must be in the range of 0 to 3 (inclusive)
Pleased enter column: -2
Columns must be in the range of 0 to 3 (inclusive)
Pleased enter column: 2
Pleased enter row: a
Invalid input: a
Pleased enter row: 72
Rows must be in the range of 5 to 15(exclusive)
Pleased enter row: 9
9, 2
Использовать
isdigit()
чтобы проверить, представляет ли строка действительное целое число.
Вы можете использовать рекурсивную функцию.
def ask():
answer = input("Please enter amount to convert: ")
if not answer.isdigit():
print("Invalid")
return ask()
Gbp = int(answer)
ask()
Или цикл while
while True:
answer = input("Please enter amount to convert: ")
if not answer.isdigit():
print("Invalid")
continue
Код ниже может помочь.
age=(lambda i,f: f(i,f))(input("Please enter your age: "),lambda i,f: i if i.isdigit() else f(input("Please enter your age: "),f))
print("You are able to vote in the united states" if int(age)>=18 else "You are not able to vote in the united states",end='')
Если вы хотите иметь максимальное количество попыток, скажем, 3, используйте приведенный ниже код
age=(lambda i,n,f: f(i,n,f))(input("Please enter your age: "),1,lambda i,n,f: i if i.isdigit() else (None if n==3 else f(input("Please enter your age: "),n+1,f)))
print("You are able to vote in the united states" if age and int(age)>=18 else "You are not able to vote in the united states",end='')
Примечание: здесь используется рекурсия.
Вы можете попытаться преобразовать его в целое число, но попросите пользователя повторить, если это не сработает.
while True:
age = input('Please enter your age: ')
try:
age_int = int(age)
if age_int >= 18:
print('You can vote in the United States!')
else:
print('You cannot vote in the United States.')
break
except:
print('Please enter a meaningful answer.')
Цикл while выполняется до тех пор, пока пользователь не ввел осмысленный ответ, но прерывается, если он имеет смысл.
Принять ввод как строку и использовать isdigit(), чтобы проверить, что ввод содержит только цифры, а не пустой, не может быть -ve
while(True):
#take input as string
name = input('Enter age : ')
#check if valid age, only digits
print( name.isdigit() )
run output :
Enter age : 12
True
Enter age :
False
Enter age : qwd
False
Enter age : dw3
False
Enter age : 21de
False
Enter age : 1
True
Enter age : -1
False
Простое решение:
while True:
age = int(input("Please enter your age: "))
if (age<=0) or (age>120):
print('Sorry, I did not understand that.Please try again')
continue
else:
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.")
break
Объяснение приведенного выше кода: Для правильного возраста он должен быть положительным и не должен превышать нормальный физический возраст, например, например, максимальный возраст составляет 120 лет.
Затем мы можем запросить у пользователя возраст, и если введенный возраст отрицательный или больше 120, мы считаем его недействительным и просим пользователя повторить попытку.
После ввода действительного ввода мы выполняем проверку (с помощью вложенного оператора if-else), составляет ли возраст>=18 или наоборот, и печатаем сообщение о том, имеет ли пользователь право голосовать.