我正在编写一个接受用户输入的程序。
#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)
使用自定义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='')
注意:这里使用递归。