Запрос пользователя на ввод, пока он не даст действительный ответ

Я пишу программу, которая должна принимать входные данные от пользователя.

#note: Python 2.7 users should use `raw_input`, the equivalent of 3.X `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, но бессмысленным в этом контексте?

Ответ 1

Самый простой способ сделать это - поместить метод input в цикл while. Используйте continue, когда вы получаете неправильный ввод, и break вне цикла, когда вы удовлетворены.

Когда ваш ввод может вызвать исключение

Используйте try и except, чтобы определить, когда пользователь вводит данные, которые невозможно проанализировать.

while True:
    try:
        # Note: Python 2.x users should use raw_input, the equivalent of 3.x 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 ошибок подряд", но вы недооцениваете изобретательность дураков!

Ответ 2

Зачем вам делать 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.

это будет работать, поскольку возраст никогда не будет иметь значения, которое не имеет смысла, а код следует логике вашего "бизнес-процесса"

Ответ 3

Хотя принятый ответ удивителен. Я также хотел бы поделиться быстрым взломом для этой проблемы. (Это также решает проблему отрицательного возраста.)

f=lambda age: (age.isdigit() and ((int(age)>=18  and "Can vote" ) or "Cannot vote")) or \
f(input("invalid input. Try again\nPlease enter your age: "))
print(f(input("Please enter your age: ")))

PS Этот код для Python 3.x.

Ответ 4

Итак, я недавно возился с чем-то похожим на это, и я придумал следующее решение, которое использует способ получения ввода, который отклоняет нежелательную информацию, прежде чем она будет проверена каким-либо логическим способом.

read_single_keypress() любезно предоставлено fooobar.com/questions/21608/...

def read_single_keypress() -> str:
    """Waits for a single keypress on stdin.
    -- from :: /questions/21608/how-do-i-make-python-to-wait-for-a-pressed-key/160320#160320
    """

    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() в том же модуле, чтобы разрешить, скажем, только три цифры.

Ответ 5

Функциональный подход или "смотри, мама без петель!":

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

Как это работает?

  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
    
  2. 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 does not care now
    it does not care now
    # and so on...
    
  3. Мы используем 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.

Другие правила проверки:

  1. Строковые методы: Конечно, вы можете использовать другие строковые методы, такие как str.isalpha, чтобы получить только буквенные строки, или str.isupper, чтобы получить только заглавные буквы. См. документы для получения полного списка.

  2. Тестирование членства:
    Есть несколько разных способов сделать это. Одним из них является использование __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
    
  3. Сравнение чисел:
    Есть полезные методы сравнения, которые мы можем использовать здесь. Например, для __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
    

    Или, если вам не нравится использование более сложных методов (dunder = двойное подчеркивание), вы всегда можете определить свои собственные функции или использовать функции из модуля operator.

  4. Путь существования:
    Здесь можно использовать библиотеку pathlib и ее метод Path.exists :

    from itertools import chain, repeat
    from pathlib import Path
    
    prompts = chain(["Enter a path: "], repeat("This path does not 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 does not exist! Try again:  1
    This path does not 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!

Предварительная обработка входных данных:

Иногда мы не хотим отклонять ввод, если пользователь случайно предоставил его IN CAPS или с пробелом в начале или конце строки. Чтобы учесть эти простые ошибки, мы можем предварительно обработать входные данные, применяя методы str.lower и str.strip. Например, в случае тестирования членства код будет выглядеть следующим образом:

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)
lowercased_replies = map(str.lower, replies)
stripped_replies = map(str.strip, lowercased_replies)
valid_response = next(filter(fruits.__contains__, stripped_replies))
print(valid_response)
Enter a fruit:  duck
I don't know this one! Try again:     Orange
orange

В случае, когда у вас есть много функций, которые можно использовать для предварительной обработки, может быть проще использовать функцию, выполняющую композицию функций. Например, используя здесь:

from itertools import chain, repeat

from lz.functional import compose

fruits = {'apple', 'orange', 'peach'}
prompts = chain(["Enter a fruit: "], repeat("I don't know this one! Try again: "))
replies = map(input, prompts)
process = compose(str.strip, str.lower)  # you can add more functions here
processed_replies = map(process, replies)
valid_response = next(filter(fruits.__contains__, processed_replies))
print(valid_response)
Enter a fruit:  potato
I don't know this one! Try again:   PEACH
peach

Объединение правил проверки:

Например, для простого случая, когда программа запрашивает возраст от 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

К сожалению, если кому-то нужно настраиваемое сообщение для каждого неудачного случая, то, боюсь, нет достаточно функционального способа. Или, по крайней мере, я не смог найти.

Ответ 6

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."

Ответ 7

Чтобы отредактировать код и исправить ошибку:

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")

Ответ 8

Использование Нажмите:

Click - это библиотека для интерфейсов командной строки, которая предоставляет функциональные возможности для запроса правильного ответа от пользователя.

Простой пример:

import 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 your age?", type=click.IntRange(1, 120))
print(age)
What your age?: 
 a
Error: a is not a valid integer
What your age?: 
 0
Error: 0 is not in the valid range of 1 to 120.
What your age?: 
 5
5

Мы также можем указать только одно из ограничений, min или max:

age = click.prompt("What your age?", type=click.IntRange(min=14))
print(age)
What your age?: 
 0
Error: 0 is smaller than the minimum valid value 14.
What 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

Ответ 9

Основываясь на замечательных предложениях Даниэля Q и Патрика Артнера, здесь представлено еще более обобщенное решение.

# 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.")

Ответ 10

Попробуйте следующее: -

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('[[email protected]#$%^&*()_+{}":/\']+$').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')

Ответ 11

В то время как блок 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.")

Ответ 12

Используйте try catch с бесконечным циклом. Чтобы проверить пустую строку, используйте инструкцию 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')

Ответ 13

Это будет продолжаться, попросив пользователя ввести номер, пока не будет введен правильный номер:

#note: Python 2.7 users should use raw_input, the equivalent of 3.X 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 ")

Ответ 14

Еще одно решение для использования проверки ввода с использованием настраиваемой 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

Ответ 15

Хороший вопрос! Вы можете попробовать следующий код для этого. знак равно

Этот код использует ast.literal_eval(), чтобы найти тип данных ввода (age). Далее следует следующий алгоритм:

  1. Попросите пользователя ввести свой 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.") 

Ответ 16

Постоянный пользовательский ввод с использованием рекурсивной функции:

строка

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)

Ответ 17

Вы всегда можете применить простую логику 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

Это будет бесконечный туалет, и вас попросят ввести возраст бесконечно.

Ответ 18

Вы можете написать более общую логику, чтобы позволить пользователю вводить только определенное количество раз, поскольку один и тот же вариант использования возникает во многих реальных приложениях.

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.

Ответ 19

Используйте оператор "while", пока пользователь не вводит истинное значение, и если входное значение не является числом или оно имеет значение null, пропустите его и попробуйте снова и так далее. В примере я попытался ответить на действительно ваш вопрос. Если мы предположим, что наш возраст составляет от 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 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.")

Ответ 20

Вы можете сделать оператор ввода while True loop, чтобы он неоднократно запрашивал вход пользователя и затем прерывал этот цикл, если пользователь вводит ответ, который вы хотите. И вы можете использовать try и except blocks для обработки недопустимых ответов.

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 такова, что если пользователь вводит строку вместо целого числа, программа не вернет "Вы не можете голосовать в Соединенных Штатах".

Ответ 21

Здесь более чистое, более обобщенное решение, которое позволяет избежать повторяющихся блоков 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)