在给出正确/可接受的答案之前,如何重复提问?

扎眼的阳光 python 398

原文标题How do I make a question repeat until the correct/acceptable answer is given? 

我正在编写一个接受用户输入的程序。

#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​​,但在这种情况下是荒谬的?

原文链接:https://stackoverflow.com//questions/71685873/how-do-i-make-a-question-repeat-until-the-correct-acceptable-answer-is-given

回复

我来回复
  • 完成此操作的最简单方法是将input方法放入 while 循环中。当您输入错误时使用continue,当您满意时使用break退出循环。

    当您的输入可能引发异常时

    使用tryexcept来检测用户何时输入了无法解析的数据。

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

    常见的陷阱,以及为什么你应该避免它们

    Redundant的冗余使用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方法短,但它违反了软件开发的不要重复自己的原则。这增加了系统中出现错误的可能性。如果你想通过更改inputraw_input来向后移植到 2.7,但是不小心只改了第一个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
    

    这似乎在大多数情况下都可以正常工作,但是如果用户输入无效数据的次数足够多,则脚本将以 aRuntimeError: maximum recursion depth exceeded 终止。你可能认为“没有傻瓜会连续犯1000个错误”,但你低估了傻瓜的聪明才智!

    2年前 0条评论
  • 你为什么要做 awhile 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.
    

    这将起作用,因为年龄永远不会具有没有意义的值,并且代码遵循您的“业务流程”的逻辑

    2年前 0条评论
  • 虽然接受的答案是惊人的。我还想分享一个针对这个问题的快速破解方法。 (这也解决了负年龄问题。)

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

    P.S。This code is for python 3.x.

    2年前 0条评论
  • 功能接近者“看起来妈妈没有循环!”:

    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([“输入一个数字:”], repeat(“不是数字!再试一次:”)) itertools.chain 和 itertools.repeat 的组合将创建一个迭代器,它会产生字符串“输入一个数字:”一次, 和“不是数字!再试一次:” 无限次:for prompt in prompts: print(prompt) Enter a number: Not a number!再试一次:不是数字!再试一次:不是数字!再试一次:# … 等等
    2. replies = map(input, prompts) – 这里的 map 会将上一步中的所有提示字符串应用到输入函数。例如:在回复中回复:print(reply) 输入数字:aaNot a number!再试一次:11不是数字!再试一次:它现在不在乎它现在不在乎#等等……
    3. 我们使用 filter 和 str.isdigit 来过滤掉那些只包含数字的字符串: only_digits = filter(str.isdigit, replies)for reply in only_digits: print(reply) Enter a number: aNot a number!再试一次:11不是数字!再试一次:22不是数字!再试一次:b不是数字!再试一次:# 等等……并且只获取我们使用 next 的第一个仅数字字符串。

    其他验证规则:

    1. 字符串方法:当然,您可以使用其他字符串方法,例如 str.isalpha 仅获取字母字符串,或 str.isupper 仅获取大写字母。有关完整列表,请参阅文档。
    2. 会员测试:
      有几种不同的方法来执行它。其中之一是使用 __contains__ 方法: from itertools import chain, repeatfruits = {‘apple’, ‘orange’, ‘peach’}prompts = chain([“Enter a fruit:”], repeat(“I don’t know这个!再试一次:”))replies = map(input, prompts)valid_response = next(filter(fruits.__contains__, replies))print(valid_response) 输入一个水果:1我不知道这个!再试一次:foo我不认识这个!再试一次:appleapple
    3. 数字比较:
      我们可以在这里使用一些有用的比较方法。例如对于 __lt__ ( < ): from itertools import chain, repeatprompts = chain([“输入一个正数:”], repeat(“我需要一个正数!再试一次:”))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) 输入一个正数:我需要一个正数数字!再试一次:-5我需要一个正数!再试一次:0我需要一个正数!再试一次:55.0
      或者,如果您不喜欢使用 dunder 方法(dunder = 双下划线),您可以随时定义自己的函数,或使用 operator 模块中的函数。
    4. 路径存在:
      这里可以使用 pathlib 库及其 Path.exists 方法: from itertools import chain, repeatfrom pathlib import Pathprompts = chain([“请输入路径:”], repeat(“此路径不存在!再试一次:”)) replies = map(input, prompts)paths = map(Path, replies)valid_response = next(filter(Path.exists, paths))print(valid_response) 输入路径:ab c这个路径不存在!再试一次:1这条路径不存在!再试一次:existing_file.txtexisting_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
    

    不幸的是,如果有人需要为每个失败的案例定制消息,那么恐怕没有漂亮的功能方式。或者,至少,我找不到一个。

    2年前 0条评论
  • 使用点击:

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

    我们也可以只指定一个限制,minmax

    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
    

    使用路径和文件:

    使用 aclick.Pathtype 我们可以检查现有路径并解决它们:

    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
    
    2年前 0条评论
  • 所以,我最近在搞类似这样的事情,我想出了以下解决方案,它使用一种获取拒绝垃圾的输入的方式,甚至在以任何逻辑方式检查它之前。

    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!
    $ _
    

    请注意,此实现的本质是在读取非数字内容时立即关闭标准输入。 a后我没有按回车,但我需要在数字后输入。

    您可以将其与同一模块中的thismany()函数合并,以仅允许三个数字。

    2年前 0条评论
  • 我是 Unix 哲学“做一件事,做好”的忠实粉丝。捕获用户输入并对其进行验证是两个独立的步骤:

    • 使用 get_input 提示用户输入,直到输入正常
    • 使用可以传递给 get_input 的验证器函数进行验证

    它可以保持简单(Python 3.8+,使用海象运算符):

    def get_input(
        prompt="Enter a value: ",
        validator=lambda x: True,
        error_message="Invalid input. Please try again.",
    ):
        while not validator(value := input(prompt)):
            print(error_message)
        return value
    
    def is_positive_int(value):
        try:
            return int(value) >= 0
        except ValueError:
            return False
    
    if __name__ == "__main__":
        val = get_input("Give a positive number: ", is_positive_int)
        print(f"OK, thanks for {val}")
    

    样品运行:

    Give a positive number: -5
    Invalid input. Please try again.
    Give a positive number: asdf
    Invalid input. Please try again.
    Give a positive number:
    Invalid input. Please try again.
    Give a positive number: 42
    OK, thanks for 42
    

    在 Python < 3.8 中,您可以像这样使用get_input

    def get_input(
        prompt="Enter a value: ",
        validator=lambda x: True,
        error_message="Invalid input. Please try again.",
    ):
        while True:
            value = input(prompt)
            if validator(value):
                return value
            print(error_message)
    

    您还可以在终止应用程序之前处理KeyboardInterrupt并打印友好的退出消息。如果需要,可以使用计数器来限制允许的重试次数。

    2年前 0条评论
  • 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年前 0条评论
  • 使用 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")
    
    2年前 0条评论
  • 试试这个: –

    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')
    
    2年前 0条评论
  • 基于 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.")
    
    2年前 0条评论
  • 您始终可以应用简单的 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
    

    这将是一个无限的厕所,你会被要求无限期地进入这个时代。

    2年前 0条评论
  • 虽然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.")
    
    2年前 0条评论
  • 您可以编写更通用的逻辑以允许用户仅输入特定次数,因为在许多实际应用程序中都会出现相同的用例。

    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.
    
    2年前 0条评论
  • 您可以将输入语句设为 while True 循环,以便它反复询问用户输入,然后在用户输入您想要的响应时中断该循环。您可以使用 try 和 except 块来处理无效响应。

    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 变量只是为了如果用户输入一个字符串而不是一个整数,程序将不会返回“你不能在美国投票”。

    2年前 0条评论
  • 使用“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.")
    
    2年前 0条评论
  • 好问题!您可以为此尝试以下代码。 =)

    此代码使用ast.literal_eval() 来查找输入的数据类型(age)。然后它遵循以下算法:

    1. 要求用户输入她/他的年龄。
      1.1. If age is float or int data type:
    2. 检查 age>=18 是否。如果 age>=18 ,打印适当的输出并退出。
    3. 检查是否 0
    4. 如果 age<=0 ,要求用户再次输入一个有效的年龄数字,(
      i.e.
      返回步骤 1。)
      1.2. If age is not float or int data type, then ask user to input her/his age again (
      i.e.
      返回步骤 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.") 
    
    2年前 0条评论
  • 使用递归函数的持久用户输入:

    细绳

    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)
    
    2年前 0条评论
  • 您可以尝试将其转换为整数,但如果不起作用,请用户重复。

    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 循环就会运行,但如果有意义就会中断。

    2年前 0条评论
  • 使用自定义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
    
    2年前 0条评论