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

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


当前回答

使用递归函数的持久用户输入:

字符串

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)

其他回答

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

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

使用自定义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

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

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

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

注意:这里使用递归。