사용자가 유효한 응답을 제공 할 때까지 입력 요청

Apr 25 2014

사용자의 입력을 받아들이는 프로그램을 작성 중입니다.

#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하지만 의미가없는 과 같은 값을 어떻게 거부 할 수 있습니까?

답변

776 Kevin Apr 25 2014 at 20:31

이를 수행하는 가장 간단한 방법은 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방법 보다 짧기 때문에 매력적으로 보일 수 있지만 소프트웨어 개발 의 Do n't Repeat Yourself 원칙을 위반합니다 . 이렇게하면 시스템에서 버그가 발생할 가능성이 높아집니다. 으로 변경 input하여 2.7로 백 포트하고 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 번의 실수를하지 않을 것"이라고 생각할 수 있지만, 바보의 독창성을 과소 평가하고 있습니다!

46 StevenStip Jan 14 2016 at 19:43

while True당신이 원하는 것은 나이가 생기면 멈추는 것이기 때문에 왜 당신은 왜 a를 하고 나서이 루프에서 벗어나고 당신이 원하는 것은 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.

나이는 의미가없는 가치를 가지지 않고 코드가 "비즈니스 프로세스"의 논리를 따르기 때문에 이것은 작동합니다.

26 aaveg Jun 29 2015 at 06:29

받아 들여지는 대답은 놀랍습니다. 이 문제에 대한 빠른 해킹도 공유하고 싶습니다. (이것은 부정적인 연령 문제도 처리합니다.)

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

추신이 코드는 python 3.x 용입니다.

17 Georgy May 10 2019 at 23:47

기능적 접근 또는 " 루프가없는 것 같아! ":

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.chainitertools.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 doesn't care now
    it doesn't 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 메서드 (dunder = 이중 밑줄)를 사용하는 것을 좋아하지 않는 경우 언제든지 자신의 함수를 정의하거나 operator모듈 의 함수를 사용할 수 있습니다 .

  4. 경로 존재 :
    여기에서 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!

입력 데이터 전처리 :

사용자가 실수로 대문자 로 입력 하거나 문자열의 시작 또는 끝에 공백이 있는 입력을 거부하고 싶지 않을 때가 있습니다. 이러한 간단한 실수를 고려하기 위해 str.lowerstr.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

누군가가 각 실패한 경우에 사용자 정의 메시지를 필요로하는 경우 불행하게도, 다음, 난 두려워, 어떤이없는 매우 기능적인 방법입니다. 또는 적어도 하나를 찾을 수 없습니다.

13 cat Jan 31 2016 at 10:47

그래서 저는 최근에 이와 비슷한 것을 엉망으로 만들었고, 논리적으로 확인하기 전에 정크를 거부하는 입력을 얻는 방법을 사용하는 다음 솔루션을 찾았습니다.

read_single_keypress()예의 https://stackoverflow.com/a/6599441/4532996

def read_single_keypress() -> str:
    """Waits for a single keypress on stdin.
    -- from :: https://stackoverflow.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!
$ _

이 구현의 특성은 숫자가 아닌 것을 읽는 즉시 stdin을 닫는다는 것입니다. 나는 뒤에 엔터를 치지 a않았지만 숫자 뒤에 필요했습니다.

thismany()이를 동일한 모듈 의 함수 와 병합하여 예를 들어 3 자리 만 허용 할 수 있습니다.

12 Georgy May 11 2019 at 03:17

클릭 사용 :

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

문자열 값을 자동으로 float로 변환하는 방법에 유의하십시오.

값이 범위 내에 있는지 확인 :

다양한 사용자 정의 유형이 제공됩니다. 특정 범위의 숫자를 얻으려면 다음을 사용할 수 있습니다 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
3 ojasmohril Jun 23 2016 at 17:34
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."
2 JoãoManuelRodrigues Nov 28 2018 at 21:52

Daniel Q와 Patrick Artner의 훌륭한 제안을 바탕으로 더욱 일반화 된 솔루션이 있습니다.

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

어설 션 검사는 꺼져있을 수 있지만 유효성 검사는 견고성을 제공하기 위해 항상 켜져 있어야하므로 대신 명시 적 ifraise문을 선택했습니다 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.")
1 PratikAnand Apr 30 2017 at 16:29

이걸로 해봐:-

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')
1 np8 Oct 30 2020 at 14:12

그래, 나는 🎉 로부터 6 년 늦었지만 이 질문은 더 최신 답변을받을 가치가 있습니다.

우려의 분리

저는 유닉스 철학 "한 가지만하고 잘해라 " 의 열렬한 팬입니다 . 이러한 유형의 문제에서는 문제를 다음과 같이 나누는 것이 좋습니다.

  • 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 
2Cubed May 31 2016 at 03:47

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.")
SiddharthSatpathy Dec 18 2018 at 13:17

좋은 질문! 이를 위해 다음 코드를 시도 할 수 있습니다. =)

이 코드는 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이 아닌 경우 사용자에게 나이를 다시 입력하도록 요청합니다 ( 예 : 1 단계로 돌아 가기).floatint

다음은 코드입니다.

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.") 
Ep1c1aN Jul 01 2019 at 16:36

언제든지 간단한 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

이것은 무한한 화장실이 될 것이며 무기한으로 나이를 입력하라는 요청을 받게 될 것입니다.

Liju Aug 17 2020 at 15:24

아래 코드가 도움이 될 수 있습니다.

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='')

참고 : 이것은 재귀를 사용합니다.

behnaz.sheikhi Sep 09 2020 at 19:30

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