Python 请求用户输入,直到他们给出有效响应
我正在编写一个接受用户输入的程序Python 请求用户输入,直到他们给出有效响应,python,Python,我正在编写一个接受用户输入的程序 #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 t
#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
请输入您的年龄:23岁
你可以在美国投票!
但如果用户输入无效数据,则会失败:
C:\Python\Projects>canyouvote.py
请输入您的年龄:dickety六岁 回溯最近一次呼叫上次: 文件canyouvote.py,第1行,在 年龄=首次输入请输入您的年龄: ValueError:基数为10的int的文本无效:“dickety六” 我希望程序再次请求输入,而不是崩溃。像这样: C:\Python\Projects>canyouvote.py
请输入您的年龄:dickety六岁 对不起,我不明白。 请输入您的年龄:26岁 你可以在美国投票! 当输入非感官数据时,如何使程序请求有效输入而不是崩溃
我如何拒绝像-1这样的值,它是一个有效的int,但在这种情况下毫无意义?实现这一点的最简单方法是将输入方法放入while循环中。当你得到错误的输入时使用,当你满意时打破循环 当您的输入可能引发异常时 用于检测用户何时输入无法解析的数据
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.")
常见的陷阱,以及您应该避免它们的原因
冗余输入语句的冗余使用
这种方法可行,但通常被认为是拙劣的风格:
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方法短,但它违反了软件开发的原则。这会增加系统中出现错误的可能性。如果您想通过将输入更改为raw_输入,而意外地仅更改上面的第一个输入,从而将后端口转换为2.7,该怎么办?这是一个即将发生的语法错误
递归会毁掉你的堆栈
如果您刚刚了解了递归,您可能会尝试在get_non_negative_int中使用它,以便处理while循环
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
这似乎在大多数情况下都可以正常工作,但如果用户输入无效数据的次数足够多,脚本将以运行时错误终止:超过最大递归深度。你可能认为没有傻瓜会连续犯1000个错误,但你低估了傻瓜的聪明才智 尽管公认的答案令人惊讶。我还想分享一下这个问题的快速解决方法。这也解决了消极的年龄问题
f=lambda age: (age.isdigit() and ((int(age)>=18 and "Can vote" ) or "Cannot vote")) or \
f(input("invalid input. Try again\nPlease enter your age: "))
print(f(input("Please enter your age: ")))
另外,这段代码是针对Python3.x编写的。为什么要执行一段while True,然后跳出这个循环,而您也可以将您的需求放在while语句中,因为您只想在达到年龄后停止
age = None
while age is None:
input_value = input("Please enter your age: ")
try:
# try and convert the string input to a number
age = int(input_value)
except ValueError:
# tell the user off
print("{input} is not a number, please enter a number only".format(input=input_value))
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: *potato*
potato is not a number, please enter a number only
Please enter your age: *5*
You are not able to vote in the United States.
这将起作用,因为年龄永远不会有一个没有意义的值,代码遵循您的业务流程的逻辑。因此,我最近正在处理类似的问题,我提出了以下解决方案,它使用一种在以任何逻辑方式检查输入之前拒绝垃圾的方法 阅读\u单键\u按键礼貌 您可以找到完整的模块 例如:
$ ./input_constrain.py
can you vote? age : a
sorry, age can only consist of digits.
$ ./input_constrain.py
can you vote? age : 23<RETURN>
your age is 23
You can vote!
$ _
请注意,此实现的本质是,一旦读取非数字的内容,它就会关闭stdin。a后我没有按enter键,但我需要按数字
您可以将它和同一模块中的thismany函数合并,以便只允许(比如)三位数字。虽然try/except块可以工作,但完成此任务的更快更干净的方法是使用str.isdigit
您可以编写更通用的逻辑,允许用户只输入特定的次数,因为在许多实际应用程序中都会出现相同的用例
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.
试试这个:-
def takeInput(required):
print 'ooo or OOO to exit'
ans = raw_input('Enter: ')
if not ans:
print "You entered nothing...!"
return takeInput(required)
## FOR Exit ##
elif ans in ['ooo', 'OOO']:
print "Closing instance."
exit()
else:
if ans.isdigit():
current = 'int'
elif set('[~!@#$%^&*()_+{}":/\']+$').intersection(ans):
current = 'other'
elif isinstance(ans,basestring):
current = 'str'
else:
current = 'none'
if required == current :
return ans
else:
return takeInput(required)
## pass the value in which type you want [str/int/special character(as other )]
print "input: ", takeInput('str')
使用while语句,直到用户输入一个真值,如果输入值不是一个数字或是一个空值,则跳过它并尝试再次询问,以此类推。 在这个例子中,我试图真实地回答你的问题。如果我们假设我们的年龄在1到150之间,那么输入值被接受,否则它是一个错误的值。 对于终止程序,用户可以使用0键并将其作为值输入 注意:阅读代码顶部的注释
您可以将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变量的作用是,如果用户输入的是字符串而不是整数,程序将不会返回,您将无法在美国投票。使用自定义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语句,而不是断言,
因为断言检查可能被关闭,
而验证应始终处于开启状态,以提供健壮性
这可用于获取不同类型的输入,
具有不同的验证条件。
例如:
# 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.")
好问题!您可以为此尝试以下代码= 此代码用于查找输入年龄的数据类型。然后遵循以下算法: 请用户输入她/他的年龄 1.1。如果年龄是float或int数据类型: 检查年龄是否大于等于18岁。如果年龄>=18,打印适当的输出并退出
使用递归函数检查是否0持久用户输入:
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
一串
整数
最后,问题要求:
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)
或者看,妈妈,不要打圈
从itertools导入链,重复
prompts=chain[输入数字:],不是数字!再试一次:
回复=mapinput,提示
valid_response=nextfilterstr.isdigit,回复
打印有效的\u响应
输入一个数字:a
不是数字!再试一次:b
不是数字!再试一次:1
1.
或者,如果您希望将错误的输入消息与其他答案中的输入提示分隔开:
prompt\u msg=输入一个数字:
bad\u input\u msg=对不起,我不明白。
prompts=链[prompt\u msg],重复“\n”。加入[bad\u input\u msg,prompt\u msg]
回复=mapinput,提示
valid_response=nextfilterstr.isdigit,回复
打印有效的\u响应
输入一个数字:a
对不起,我不明白。
输入一个数字:b
对不起,我不明白。
输入一个数字:1
1.
它是如何工作的?
prompts=chain[输入数字:],不是数字!再试一次:
和的组合将创建一个迭代器
这将产生字符串输入一个数字:一次,而不是一个数字!重试:无限次:
对于提示中的提示:
打印提示
输入一个数字:
不是数字!再试一次:
不是数字!再试一次:
不是数字!再试一次:
... 等等
replies=mapinput,prompts-此处将上一步中的所有提示字符串应用于函数。例如。:
在答复中答复:
打印答复
输入一个数字:a
A.
不是数字!再试一次:1
1.
不是数字!再试一次:现在不管了
现在不在乎了
等等
我们使用和过滤掉那些只包含数字的字符串:
只有_digits=filterstr.isdigit,回复
对于仅以_位数字回复:
打印答复
输入一个数字:a
不是数字!再试一次:1
1.
不是数字!再试一次:2
2.
不是数字!再试一次:b
不是数字!再试一次:等等。。。
为了只得到第一个数字,我们只使用字符串。
其他验证规则:
字符串方法:当然,您可以使用其他字符串方法,比如只获取字母字符串,或者只获取大写字母。有关完整列表,请参阅
会员资格测试:
有几种不同的执行方法。其中之一是通过使用方法:
从itertools导入链,重复
水果={‘苹果’、‘橘子’、‘桃子’}
prompts=chain[输入水果:],重复我不知道这个!再试一次:
回复=mapinput,提示
有效的\u响应=nextfilterfruits.\uuu包含\uuuuuu个响应
打印有效的\u响应
输入一个水果:1
我不知道这个!再试一次:foo
我不知道这个!再试一次:苹果
苹果
数字比较:
我们可以在这里使用一些有用的比较方法。例如,对于使用:
Click是一个用于命令行界面的库,它提供了向用户请求有效响应的功能
简单的例子:
import click
number = click.prompt('Please enter a number', type=float)
print(number)
请输入一个数字:
A.
错误:a不是有效的浮点值
请输入一个数字:
10
10
请注意它是如何将字符串值自动转换为浮点值的
检查值是否在范围内:
提供了不同的服务。要获取特定范围内的数字,我们可以使用IntRange:
你几岁
A.
错误:a不是有效的整数
你几岁
0
错误:0不在1到120的有效范围内。
你几岁
5.
5.
我们也可以只指定一个限制,最小或最大:
你几岁
0
错误:0小于最小有效值14。
你几岁
18
18
会员资格测试:
使用click.Choice类型。默认情况下,此检查区分大小写
choices = {'apple', 'orange', 'peach'}
choice = click.prompt('Provide a fruit', type=click.Choice(choices, case_sensitive=False))
print(choice)
提供水果苹果、桃子、橘子:
香蕉
错误:无效选择:香蕉。选择苹果、桃子、橘子
提供水果苹果、桃子、橘子:
橙色
橙色
使用路径和文件:
使用click.Path类型,我们可以检查现有路径并解析它们:
path = click.prompt('Provide path', type=click.Path(exists=True, resolve_path=True))
print(path)
提供路径:
不存在
错误:路径不存在不存在。
提供路径:
现有文件夹
'/path/to/existing_文件夹
可以通过单击来读取和写入文件。文件:
在哪个文件中写入数据?:
您可以始终应用简单的if-else逻辑,并在代码中添加一个以上的if逻辑 还有一个for循环 尽管如此: 年龄=首次输入请输入您的年龄: 如果年龄大于等于18岁: 你可以在美国投票! 如果年龄<18岁且年龄>0: 你不能在美国投票。 其他: 打印错误的字符,输入必须是数字 持续
这将是一个无限的厕所,你将被要求无限期地进入这个年龄。简单的解决方案是:
while True:
age = int(input("Please enter your age: "))
if (age<=0) or (age>120):
print('Sorry, I did not understand that.Please try again')
continue
else:
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.")
break
上述代码的解释:
有效年龄应为正值,且不应超过正常生理年龄,例如,最大年龄为120岁
我们可以询问用户年龄,如果年龄输入为负或大于120,我们认为是无效输入,并要求用户再试一次。 输入有效输入后,我们使用嵌套的if else语句检查年龄是否大于等于18岁,反之亦然,并在下面的代码中打印一条消息,说明用户是否有资格投票
年龄=λi,f:fi,finput请输入您的年龄:,λi,f:i如果i.isdigit else Finput请输入您的年龄:,f 打印如果intage>=18,您可以在美国投票,否则您不能在美国投票,结束= 如果您想进行最大限度的尝试,比如说3次,请使用下面的代码 年龄=λi,n,f:fi,n,finput请输入您的年龄:,1,λi,n,f:i如果i.isdigit else无如果n==3其他finput请输入您的年龄:,n+1,f Print如果年龄和年龄>=18岁,您可以在美国投票,否则您不能在美国投票,结束=注意:这使用递归。使用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")
是的,我晚了6年才开始使用isdigit检查字符串是否代表有效整数
可以使用递归函数
def ask():
answer = input("Please enter amount to convert: ")
if not answer.isdigit():
print("Invalid")
return ask()
Gbp = int(answer)
ask()
或者一段时间
while True:
answer = input("Please enter amount to convert: ")
if not answer.isdigit():
print("Invalid")
continue
Gbp = int(answer)
请注意,这段代码是递归的,但这里不需要递归,正如Kevin所说,它可能会毁掉你的堆栈。@PM2Ring-你是对的。但我在这里的目的只是想说明短路是如何最小化和美化长代码段的。为什么要将lambda赋值给变量,只需使用def即可。def fage:远比f=lambda age清晰:在某些情况下,您可能只需要使用一次age,然后就没有使用该函数。一个人可能想使用一个函数,然后在工作完成后将其扔掉。此外,这可能不是最好的方法,但它肯定是另一种方法,这也是我的解决方案的目的。@aaveg您如何将此代码转化为实际节省用户提供的时间?阅读它很有趣,有很多例子,值得称赞。被低估的教训:不要低估傻瓜的创造力!不管怎样,我不仅会把这两个问答都投了更高的票,因为它们都很棒,而且你还与迪基六号达成了交易。干得好,@Kevin。别估计傻瓜的创造力。。。和聪明的攻击者。DOS攻击对于这类事情来说是最容易的,但其他攻击可能是可能的。@JArunMani我不认为它的风格不好,但可能不太可读。实际上,每个循环只有一个输入,循环将变得非常短,但条件可能会变得相当长…@laundmo,当然,我会释放我写入公共域的代码块。在任何情况下都可以随意使用它们,无需我的明确许可或知情。关于非代码块部分,如果您想将我的整个答案粘贴到您正在编写的一本学习Python的书中,那么让我们谈谈版税-您忘记在每次循环后增加iCount值。这并不能真正回答问题。问题是在用户给出有效响应之前获得用户输入,而不是无限期。这是一个多么彻底和美妙的答案,解释分解非常好。使用您的风格,如何剥离空白并降低输入的大小写以进行成员资格测试?我不想创建一个必须同时包含大写和小写示例的集合。我还想考虑空白输入错误。@Austin I添加了一个关于预处理的新部分。看一看,这让我想起了ReactiveX。但也许这一点最初是受到函数式语言的启发的?请输入您的年龄:dickety six:与问题中所述的崩溃相同…谢谢,这是完美的。在有效范围内循环选择一个数字正是我想要的。我认为您的一条评论中有一个bug,应该是这样的注意:Python 2.7用户应该很好地协调行动并进行更新:-您缺少一个break语句,并且printplease-enter数字是不必要的。如果您已经检测到按键,为什么要允许输入字符并到处抛出错误,而您却可以默默地忽略它们,直到得到所需的数字?@Kebman您可以这样做,但用户可能不太清楚它们可以键入什么。您缺少函数的返回。返回递归调用,但该调用不返回任何值。。。而你,当循环是无限的…@Tomerikoo它递归地问,直到答案是有效的,我想这就是被问到的。我是故意的
以一种可以将任何代码放入递归函数或while循环的方式编写它。这实际上是为一个不同的问题编写的,这个问题被标记为与这个问题的重复,所以我将它发布在这里。我的意思是,您应该使用一些场景来测试代码。在第一种情况下,Gbp=intanswer可能会返回intanswer,而在第二种情况下,可能会在某个地方出现中断
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)
import click
number = click.prompt('Please enter a number', type=float)
print(number)
age = click.prompt("What's your age?", type=click.IntRange(1, 120))
print(age)
age = click.prompt("What's your age?", type=click.IntRange(min=14))
print(age)
choices = {'apple', 'orange', 'peach'}
choice = click.prompt('Provide a fruit', type=click.Choice(choices, case_sensitive=False))
print(choice)
path = click.prompt('Provide path', type=click.Path(exists=True, resolve_path=True))
print(path)
file = click.prompt('In which file to write data?', type=click.File('w'))
with file.open():
file.write('Hello!')
# More info about `lazy=True` at:
# https://click.palletsprojects.com/en/7.x/arguments/#file-opening-safety
file = click.prompt('Which file you wanna read?', type=click.File(lazy=True))
with file.open():
print(file.read())
password = click.prompt('Enter password', hide_input=True, confirmation_prompt=True)
print(password)
number = click.prompt('Please enter a number', type=int, default=42)
print(number)
while True:
age = int(input("Please enter your age: "))
if (age<=0) or (age>120):
print('Sorry, I did not understand that.Please try again')
continue
else:
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.")
break
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")
def ask():
answer = input("Please enter amount to convert: ")
if not answer.isdigit():
print("Invalid")
return ask()
Gbp = int(answer)
ask()
while True:
answer = input("Please enter amount to convert: ")
if not answer.isdigit():
print("Invalid")
continue
Gbp = int(answer)