我正在编写一个必须接受用户输入的程序 .
#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
之类的值,但在此上下文中却没有意义呢?
16 回答
使用“while”语句直到用户输入一个真值,如果输入值不是数字或者它是一个空值,则跳过它并尝试再次询问,依此类推 . 在示例中,我试图回答真正的问题 . 如果我们假设我们的年龄在1到150之间,那么接受输入值,否则它是错误的值 . 对于终止程序,用户可以使用0键并将其作为值输入 .
为什么你会做一个
while True
,然后突破这个循环,你也可以把你的要求放在while语句中,因为你想要的就是在你有了年龄后停止?这将导致以下结果:
这将有效,因为年龄永远不会有一个没有意义的 Value ,代码遵循你的“业务流程”的逻辑
完成此操作的最简单方法是将
input
方法放在while循环中 . 当你输入错误时使用continue,当你满意时使用break
.当您的输入可能会引发异常时
使用try and catch检测用户何时输入无法解析的数据 .
实施自己的验证规则
如果要拒绝Python可以成功解析的值,可以添加自己的验证逻辑 .
结合异常处理和自定义验证
上述两种技术都可以组合成一个循环 .
将其全部封装在一个函数中
如果您需要向用户询问许多不同的值,将此代码放在函数中可能很有用,因此您不必每次都重新键入它 .
全部放在一起
您可以扩展这个想法,以创建一个非常通用的输入函数:
使用如下:
常见的陷阱,为什么你应该避免它们
冗余使用冗余输入语句
这种方法有效但通常被认为是不好的风格:
它最初看起来很有吸引力,因为它比
while True
方法短,但它违反了软件开发的原则 . 这会增加系统中出现错误的可能性 . 如果您想通过将input
更改为raw_input
来向后移植到2.7,但不小心只更改上面的第一个input
,该怎么办?这是等待发生的SyntaxError
.递归会打击你的堆栈
如果你刚刚学习了递归,你可能会想在
get_non_negative_int
中使用它,这样你就可以处理while循环了 .这似乎在大多数情况下都能正常工作,但如果用户输入的数据足够多次,脚本将以
RuntimeError: maximum recursion depth exceeded
终止 . 你可能会想到"no fool would make 1000 mistakes in a row",但是你低估了傻瓜的聪明才智!使用针对整数输入的自定义
ValidationError
和(可选)范围验证来使用输入验证的另一种解决方案:用法:
输出:
试试这个: -
这将继续要求用户输入数字,直到他们输入有效数字:
虽然
try
/except
块可以工作,但完成此任务的更快更清洁的方法是使用str.isdigit()
.基于Daniel Q和Patrick Artner的出色建议,这是一个更加通用的解决方案 .
我选择显式的
if
和raise
语句而不是assert
,因为断言检查可能会被关闭,而验证应始终打开以提供稳健性 .这可用于获得具有不同验证条件的不同类型的输入 . 例如:
或者,回答原始问题:
所以,我最近搞砸了与此类似的东西,我想出了以下解决方案,它使用一种获取输入的方法来拒绝垃圾,甚至在以任何逻辑方式检查之前 .
read_single_keypress()
礼貌https://stackoverflow.com/a/6599441/4532996你可以找到完整的模块here .
例:
请注意,这个实现的本质是,只要在
a
之后输入的东西没有输入就会关闭stdin,但我需要在数字之后 .您可以将它与同一模块中的
thismany()
函数合并为仅允许三位数 .您可以编写更多通用逻辑,以允许用户仅输入特定次数,因为在许多实际应用程序中出现相同的用例 .
虽然接受的答案是惊人的 . 我还想分享这个问题的快速入侵 . (这也解决了负面年龄问题 . )
附:此代码适用于python 2.x,可以通过更改raw_input和print函数导出到3.x.
编辑代码并修复错误:
您可以将输入语句设置为True循环,以便它反复询问用户输入,然后在用户输入您希望的响应时中断该循环 . 并且您可以使用try和except块来处理无效响应 .
var变量只是如果用户输入字符串而不是整数,程序将不会返回“您无法在美国投票” .
在循环中使用try catch with never ending . 要检查空字符串,请使用IF语句检查字符串是否为空 .
这是一个更清晰,更通用的解决方案,可以避免重复的if / else块:编写一个在字典中采用(错误,错误提示)对的函数,并使用断言进行所有的值检查 .
用法: