我正在编写一个接受用户输入的程序。
#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但无意义的值?
-1
int
完成此操作的最简单方法是将input方法放入 while 循环中。continue当您输入错误时使用,break当您满意时退出循环。
input
continue
break
使用tryandexcept来检测用户何时输入无法解析的数据。
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'))
这种方法有效,但通常被认为是糟糕的风格:
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方法短,但它违反了软件开发的不要重复自己的原则。这增加了系统中出现错误的可能性。如果您想通过更改为 向后移植到 2.7 input,raw_input但不小心只更改了input上面的第一个,该怎么办?这SyntaxError只是等待发生。
while True
raw_input
SyntaxError
如果您刚刚了解了递归,您可能很想在其中使用它,get_non_negative_int以便处理 while 循环。
get_non_negative_int
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个错误”,但你低估了傻瓜的聪明才智!
RuntimeError: maximum recursion depth exceeded