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

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

只要用户输入有意义的数据,程序就能正常工作。

Please enter your age: 23
You are able to vote in the United States!

但如果用户输入无效数据,则失败:

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'

而不是崩溃,我希望程序再次要求输入。是这样的:

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


当前回答

虽然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.")

其他回答

您可以将input语句设置为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变量是这样的,如果用户输入一个字符串而不是一个整数,程序不会返回“你不能在美国投票”。

我是Unix哲学“只做一件事并把它做好”的忠实粉丝。捕获用户输入并验证它是两个独立的步骤:

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

它可以保持简单如(Python 3.8+,使用walrus操作符):

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并打印友好的退出消息。如果需要,可以使用计数器限制允许的重试次数。

下面的代码可能会有所帮助。

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

注意:这里使用递归。

基于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)

我选择了显式的if和raise语句,而不是assert, 因为断言检查可能被关闭, 而验证应始终开启以提供健壮性。

这可以用来获得不同种类的输入, 使用不同的验证条件。 例如:

# No validation, equivalent to simple input:
anystr = validate_input("Enter any string: ")

# Get a string containing only letters:
letters = validate_input("Enter letters: ",
    cond=str.isalpha,
    onerror={ValidationError: "Only letters, please!"})

# Get a float in [0, 100]:
percentage = validate_input("Percentage? ",
    cast=float, cond=lambda x: 0.0<=x<=100.0,
    onerror={ValidationError: "Must be between 0 and 100!",
             ValueError: "Not a number!"})

或者,回答最初的问题:

age = validate_input("Please enter your age: ",
        cast=int, cond=lambda a:0<=a<150,
        onerror={ValidationError: "Enter a plausible age, please!",
                 ValueError: "Enter an integer, please!"})
if age >= 18: 
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")

您可以编写更通用的逻辑,以允许用户只输入特定次数,因为在许多实际应用程序中都会出现相同的用例。

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