要求用户输入,直到他们给出有效的回答

2024-11-15 08:36:00
admin
原创
17
摘要:问题描述:我正在编写一个接受用户输入的程序。#note: Python 2.7 users should use `raw_input`, the equivalent of 3.X's `input` age = int(input("Please enter your age: "))...

问题描述:

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

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


解决方案 1:

实现此目的的最简单方法是将input方法放入 while 循环中。continue当输入错误时使用,break当输入满意时退出循环。

当你的输入可能引发异常时

使用tryexcept检测用户何时输入无法解析的数据。

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

常见陷阱以及应避免的原因

input冗余语句的冗余使用

这种方法有效,但通常被认为是糟糕的风格:

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,但不小心只更改了上面的第一个,该怎么办inputraw_inputinput只是SyntaxError等待发生的事情。

递归会让你崩溃

如果您刚刚了解了递归,您可能会想使用它,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

在大多数情况下,这似乎可以正常工作,但如果用户输入无效数据的次数足够多,脚本将以 终止RuntimeError: maximum recursion depth exceeded。您可能会认为“没有傻瓜会连续犯 1000 个错误”,但您低估了傻瓜的聪明才智!

解决方案 2:

为什么你要先执行 awhile 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.

这会起作用,因为年龄永远不会有一个没有意义的数值,并且代码遵循你的“业务流程”的逻辑

解决方案 3:

功能方法或“看妈妈,没有循环! ”:

from itertools import chain, repeat

prompts = chain(["Enter a number: "], repeat("Not a number! Try again: "))
replies = map(input, prompts)
valid_response = next(filter(str.isdigit, replies))
print(valid_response)
Enter a number:  a
Not a number! Try again:  b
Not a number! Try again:  1
1

或者如果您希望将“错误输入”消息与输入提示分开,如其他答案中所述:

prompt_msg = "Enter a number: "
bad_input_msg = "Sorry, I didn't understand that."
prompts = chain([prompt_msg], repeat('
'.join([bad_input_msg, prompt_msg])))
replies = map(input, prompts)
valid_response = next(filter(str.isdigit, replies))
print(valid_response)
Enter a number:  a
Sorry, I didn't understand that.
Enter a number:  b
Sorry, I didn't understand that.
Enter a number:  1
1

它是如何工作的?

  1. = chain(["Enter a number: "], repeat("Not a number! Try again: "))

`itertools.chain`和
的组合`itertools.repeat`将创建一个迭代器,该迭代器将产生`"Enter a number: "`一次字符串,并产生`"Not a number! Try again: "`无数次字符串:

for prompt in prompts:

print(prompt)

Enter a number:
Not a number! Try again:
Not a number! Try again:
Not a number! Try again:

... and so on

2. `replies = map(input, prompts)`- 此处将把上一步中的`map`所有字符串应用到函数中。例如:
`prompts``input`

for reply in replies:

print(reply)

Enter a number: a
a
Not a number! Try again: 1
1
Not a number! Try again: it doesn't care now
it doesn't care now

and so on...

3. 我们使用`filter`和`str.isdigit`过滤掉只包含数字的字符串:

only_digits = filter(str.isdigit, replies)
for reply in only_digits:

print(reply)

Enter a number: a
Not a number! Try again: 1
1
Not a number! Try again: 2
2
Not a number! Try again: b
Not a number! Try again: # and so on...


为了仅获取我们使用的第一位数字字符串`next`。


其他验证规则:
-------


1. **字符串方法:**当然,您可以使用其他字符串方法,例如`str.isalpha`仅获取字母字符串或`str.isupper`仅获取大写字母。请参阅文档以获取完整列表。
2. **成员资格测试:**  

有几种不同的方法可以执行它。其中之一是使用`__contains__`方法:


from itertools import chain, repeat

fruits = {'apple', 'orange', 'peach'}
prompts = chain(["Enter a fruit: "], repeat("I don't know this one! Try again: "))
replies = map(input, prompts)
valid_response = next(filter(fruits.__contains__, replies))
print(valid_response)

Enter a fruit: 1
I don't know this one! Try again: foo
I don't know this one! Try again: apple
apple

3. **数字比较:**  

这里可以使用一些有用的比较方法。例如,对于`__lt__`( `<`):


from itertools import chain, repeat

prompts = chain(["Enter a positive number:"], repeat("I need a positive number! Try again:"))
replies = map(input, prompts)
numeric_strings = filter(str.isnumeric, replies)
numbers = map(float, numeric_strings)
is_positive = (0.).__lt__
valid_response = next(filter(is_positive, numbers))
print(valid_response)

Enter a positive number: a
I need a positive number! Try again: -5
I need a positive number! Try again: 0
I need a positive number! Try again: 5
5.0


或者,如果您不喜欢使用 dunder 方法(dunder = 双下划线),您可以始终定义自己的函数,或使用`operator`模块中的函数。
4. **路径存在:**  

这里可以使用`pathlib`库及其`Path.exists`方法:


from itertools import chain, repeat
from pathlib import Path

prompts = chain(["Enter a path: "], repeat("This path doesn't exist! Try again: "))
replies = map(input, prompts)
paths = map(Path, replies)
valid_response = next(filter(Path.exists, paths))
print(valid_response)

Enter a path: a b c
This path doesn't exist! Try again: 1
This path doesn't exist! Try again: existing_file.txt
existing_file.txt



限制尝试次数:
-------


如果你不想通过无数次地询问用户某件事来折磨他,你可以在调用时指定一个限制`itertools.repeat`。这可以与为`next`函数提供默认值相结合:


from itertools import chain, repeat

prompts = chain(["Enter a number:"], repeat("Not a number! Try again:", 2))
replies = map(input, prompts)
valid_response = next(filter(str.isdigit, replies), None)
print("You've failed miserably!" if valid_response is None else 'Well done!')

Enter a number: a
Not a number! Try again: b
Not a number! Try again: c
You've failed miserably!


预处理输入数据:
--------


*有时,如果用户不小心输入了大写字母*或在字符串的开头或结尾处有空格,我们不想拒绝输入。为了考虑到这些简单的错误,我们可以通过应用`str.lower`和`str.strip`方法来预处理输入数据。例如,对于成员资格测试的情况,代码将如下所示:


from itertools import chain, repeat

fruits = {'apple', 'orange', 'peach'}
prompts = chain(["Enter a fruit: "], repeat("I don't know this one! Try again: "))
replies = map(input, prompts)
lowercased_replies = map(str.lower, replies)
stripped_replies = map(str.strip, lowercased_replies)
valid_response = next(filter(fruits.__contains__, stripped_replies))
print(valid_response)

Enter a fruit: duck
I don't know this one! Try again: Orange
orange


如果你有许多函数用于预处理,使用执行函数组合的函数可能会更容易。例如,使用这里的一个:


from itertools import chain, repeat

from lz.functional import compose

fruits = {'apple', 'orange', 'peach'}
prompts = chain(["Enter a fruit: "], repeat("I don't know this one! Try again: "))
replies = map(input, prompts)
process = compose(str.strip, str.lower) # you can add more functions here
processed_replies = map(process, replies)
valid_response = next(filter(fruits.__contains__, processed_replies))
print(valid_response)

Enter a fruit: potato
I don't know this one! Try again: PEACH
peach


组合验证规则:
-------


对于简单的情况,例如,当程序要求输入 1 到 120 之间的年龄时,只需添加另一个`filter`:


from itertools import chain, repeat

prompt_msg = "Enter your age (1-120): "
bad_input_msg = "Wrong input."
prompts = chain([prompt_msg], repeat('
'.join([bad_input_msg, prompt_msg])))
replies = map(input, prompts)
numeric_replies = filter(str.isdigit, replies)
ages = map(int, numeric_replies)
positive_ages = filter((0).__lt__, ages)
not_too_big_ages = filter((120).__ge__, positive_ages)
valid_response = next(not_too_big_ages)
print(valid_response)


但在规则较多的情况下,最好实现一个执行逻辑连接的函数。在下面的例子中,我将使用此处的一个现成函数:


from functools import partial
from itertools import chain, repeat

from lz.logical import conjoin

def is_one_letter(string: str) -> bool:

return len(string) == 1

rules = [str.isalpha, str.isupper, is_one_letter, 'C'.__le__, 'P'.__ge__]

prompt_msg = "Enter a letter (C-P): "
bad_input_msg = "Wrong input."
prompts = chain([prompt_msg], repeat('
'.join([bad_input_msg, prompt_msg])))
replies = map(input, prompts)
valid_response = next(filter(conjoin(*rules), replies))
print(valid_response)

Enter a letter (C-P): 5
Wrong input.
Enter a letter (C-P): f
Wrong input.
Enter a letter (C-P): CDE
Wrong input.
Enter a letter (C-P): Q
Wrong input.
Enter a letter (C-P): N
N


不幸的是,如果有人需要为每个失败案例提供自定义消息,那么恐怕没有*非常*实用的方法。或者,至少我找不到。




## 解决方案 4:

 
虽然被接受的答案很棒。 我还想分享一个解决此问题的快速方法。 (这也可以解决负年龄问题。)


f=lambda age: (age.isdigit() and ((int(age)>=18 and "Can vote" ) or "Cannot vote")) or nf(input("invalid input. Try again
Please enter your age: "))
print(f(input("Please enter your age: ")))


PS此代码适用于python 3.x。




## 解决方案 5:

 
使用*点击*:
=======


*Click*是一个命令行界面库,它提供向用户询问有效响应的功能。


简单示例:


import click

number = click.prompt('Please enter a number', type=float)
print(number)

Please enter a number:
a
Error: a is not a valid floating point value
Please enter a number:
10
10.0


注意它如何自动将字符串值转换为浮点数。


检查某个值是否在某个范围内:
--------------


提供了不同的自定义类型。要获取特定范围内的数字,我们可以使用`IntRange`:


age = click.prompt("What's your age?", type=click.IntRange(1, 120))
print(age)

What's your age?:
a
Error: a is not a valid integer
What's your age?:
0
Error: 0 is not in the valid range of 1 to 120.
What's your age?:
5
5


我们也可以仅指定其中一个限制,`min`或者`max`:


age = click.prompt("What's your age?", type=click.IntRange(min=14))
print(age)

What's your age?:
0
Error: 0 is smaller than the minimum valid value 14.
What's your age?:
18
18


会员资格测试:
-------


使用`click.Choice`类型。默认情况下,此检查区分大小写。


choices = {'apple', 'orange', 'peach'}
choice = click.prompt('Provide a fruit', type=click.Choice(choices, case_sensitive=False))
print(choice)

Provide a fruit (apple, peach, orange):
banana
Error: invalid choice: banana. (choose from apple, peach, orange)
Provide a fruit (apple, peach, orange):
OrAnGe
orange


使用路径和文件:
--------


使用`click.Path`类型我们可以检查现有路径并解析它们:


path = click.prompt('Provide path', type=click.Path(exists=True, resolve_path=True))
print(path)

Provide path:
nonexistent
Error: Path "nonexistent" does not exist.
Provide path:
existing_folder
'/path/to/existing_folder


可以通过以下方式读取和写入文件`click.File`:


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())

In which file to write data?:

     # <-- provided an empty string, which is an illegal name for a file

In which file to write data?:
some_file.txt
Which file you wanna read?:
nonexistent.txt
Error: Could not open file: nonexistent.txt: No such file or directory
Which file you wanna read?:
some_file.txt
Hello!


其他示例:
-----


### 密码确认:


password = click.prompt('Enter password', hide_input=True, confirmation_prompt=True)
print(password)

Enter password:
······
Repeat for confirmation:
·
Error: the two entered values do not match
Enter password:
······
Repeat for confirmation:
······
qwerty


### 默认值:


在这种情况下,只需按下`Enter`(或使用的任何键)而不输入值,就会为您提供默认值:


number = click.prompt('Please enter a number', type=int, default=42)
print(number)

Please enter a number [42]:
a
Error: a is not a valid integer
Please enter a number [42]:

42




## 解决方案 6:

 
我非常推崇 Unix 哲学“专心做好一件事”。捕获用户输入并验证输入是两个独立的步骤:


* 提示用户输入,`get_input`直到输入正确
* 使用`validator`可以传递给的函数进行验证`get_input`


它可以保持尽可能简单(Python 3.8+,使用海象运算符):


def get_input(

prompt="Enter a value: ",
validator=lambda x: True,
error_message="Invalid input. Please try again.",

):

while not validator(value := input(prompt)):
    print(error_message)
return value

def is_positive_int(value):

try:
    return int(value) >= 0
except ValueError:
    return False

if name == "__main__":

val = get_input("Give a positive number: ", is_positive_int)
print(f"OK, thanks for {val}")

示例运行:


Give a positive number: -5
Invalid input. Please try again.
Give a positive number: asdf
Invalid input. Please try again.
Give a positive number:
Invalid input. Please try again.
Give a positive number: 42
OK, thanks for 42




---


在 Python <3.8 中你可以`get_input`这样使用:


def get_input(

prompt="Enter a value: ",
validator=lambda x: True,
error_message="Invalid input. Please try again.",

):

while True:
    value = input(prompt)
    if validator(value):
        return value
    print(error_message)

您还可以`KeyboardInterrupt`在终止应用程序之前处理并打印友好的退出消息。如果需要,可以使用计数器来限制允许的重试次数。




## 解决方案 7:

 
所以,我最近在处理类似的东西,我想出了下面的解决方案,它使用一种在以任何逻辑方式检查之前拒绝垃圾输入的方式。


`read_single_keypress()`礼貌https://stackoverflow.com/a/6599441/4532996


def read_single_keypress() -> str:

"""Waits for a single keypress on stdin.
-- from :: https://stackoverflow.com/a/6599441/4532996
"""

import termios, fcntl, sys, os
fd = sys.stdin.fileno()
# save old state
flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
attrs_save = termios.tcgetattr(fd)
# make raw - the way to do this comes from the termios(3) man page.
attrs = list(attrs_save) # copy the stored version to update
# iflag
attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK
              | termios.ISTRIP | termios.INLCR | termios. IGNCR
              | termios.ICRNL | termios.IXON )
# oflag
attrs[1] &= ~termios.OPOST
# cflag
attrs[2] &= ~(termios.CSIZE | termios. PARENB)
attrs[2] |= termios.CS8
# lflag
attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON
              | termios.ISIG | termios.IEXTEN)
termios.tcsetattr(fd, termios.TCSANOW, attrs)
# turn off non-blocking
fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
# read a single keystroke
try:
    ret = sys.stdin.read(1) # returns a single character
except KeyboardInterrupt:
    ret = 0
finally:
    # restore old state
    termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
    fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
return ret

def until_not_multi(chars) -> str:

"""read stdin until !(chars)"""
import sys
chars = list(chars)
y = ""
sys.stdout.flush()
while True:
    i = read_single_keypress()
    _ = sys.stdout.write(i)
    sys.stdout.flush()
    if i not in chars:
        break
    y += i
return y

def _can_you_vote() -> str:

"""a practical example:
test if a user can vote based purely on keypresses"""
print("can you vote? age : ", end="")
x = int("0" + until_not_multi("0123456789"))
if not x:
    print("

sorry, age can only consist of digits.")

    return
print("your age is", x, "

You can vote!" if x >= 18 else "Sorry! you can't vote")

_can_you_vote()


您可以在此处找到完整的模块。


例子:


$ ./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`,但我需要在数字之后按下回车键。


您可以将其与`thismany()`同一模块中的函数合并,以便仅允许三位数字。




## 解决方案 8:

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



## 解决方案 9:

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



## 解决方案 10:

 

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



## 解决方案 11:

 
好问题!您可以尝试以下代码。=)


此代码使用ast.literal_eval()查找**输入的数据类型**( `age`)。然后它遵循以下算法:



> 1. 要求用户输入她/他的`age`。
> 
> 
> 1.1. 如果`age`是`float`或`int`数据类型:
> 
> 
>     * 检查是否`age>=18`。如果`age>=18`,则打印适当的输出并退出。
>     * 检查是否`0<age<18`。如果`0<age<18`,则打印适当的输出并退出。
>     * 如果是`age<=0`,则要求用户再次输入有效的年龄数字(*即*返回步骤1)。1.2. 如果`age`不是`float`或`int`数据类型,则要求用户再次输入其年龄(*即*返回步骤 1)。


这是代码。


from ast import literal_eval

''' This function is used to identify the data type of input data.'''
def input_type(input_data):

try:
    return type(literal_eval(input_data))
except (ValueError, SyntaxError):
    return str

flag = True

while(flag):

age = raw_input("Please enter your age: ")

if input_type(age)==float or input_type(age)==int:
    if eval(age)>=18: 
        print("You are able to vote in the United States!") 
        flag = False 
    elif eval(age)>0 and eval(age)<18: 
        print("You are not able to vote in the United States.") 
        flag = False
    else: print("Please enter a valid number as your age.")

else: print("Sorry, I didn't understand that.") 



## 解决方案 12:

 
试试这个:-


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




## 解决方案 13:

 
使用“while”语句直到用户输入一个真值,如果输入值不是数字或为空值,则跳过它并尝试再次询问,依此类推。例如,我试图真实地回答你的问题。如果我们假设我们的年龄在 1 到 150 之间,则输入值被接受,否则就是错误的值。要终止程序,用户可以使用 0 键并将其作为值输入。



> 注意:阅读代码顶部的注释。


If your input value is only a number then use "Value.isdigit() == False".

If you need an input that is a text, you should remove "Value.isdigit() == False".

def Input(Message):

Value = None
while Value == None or Value.isdigit() == False:
    try:        
        Value = str(input(Message)).strip()
    except Exception:
        Value = None
return Value

Example:

age = 0

If we suppose that our age is between 1 and 150 then input value accepted,

else it's a wrong value.

while age <=0 or age >150:

age = int(Input("Please enter your age: "))
# For terminating program, the user can use 0 key and enter it as an a value.
if age == 0:
    print("Terminating ...")
    exit(0)
    

if age >= 18 and age <=150:

print("You are able to vote in the United States!")

else:

print("You are not able to vote in the United States.")



## 解决方案 14:

 
`if`您始终可以应用简单的 if-else 逻辑,并在循环中向您的代码添加另一个逻辑`for`。


while True:

 age = int(input("Please enter your age: "))
 if (age >= 18)  : 
     print("You are able to vote in the United States!")
 if (age < 18) & (age > 0):
     print("You are not able to vote in the United States.")
 else:
     print("Wrong characters, the input must be numeric")
     continue

这将是一个无限的厕所,你会被要求进入这个时代,无限期地。




## 解决方案 15:

 
虽然`try`/`except`块可以起作用,但完成此任务的更快、更干净的方法是使用`str.isdigit()`。


while True:

age = input("Please enter your age: ")
if age.isdigit():
    age = int(age)
    break
else:
    print("Invalid number '{age}'. Try again.".format(age=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.")



## 解决方案 16:

 
您可以编写更通用的逻辑来允许用户仅输入特定的次数,因为许多实际应用程序中都会出现相同的用例。


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.




## 解决方案 17:

 
您可以将输入语句设为 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 变量只是为了当用户输入字符串而不是整数时程序不会返回“您不能在美国投票”。




## 解决方案 18:

 
另一种使用自定义`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




## 解决方案 19:

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


### 细绳


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)




## 解决方案 20:

 
您可以尝试将其转换为整数,但如果不起作用,请用户重复。


while True:

age = input('Please enter your age: ')
try:
    age_int = int(age)
    if age_int >= 18:
        print('You can vote in the United States!')
    else:
        print('You cannot vote in the United States.')
    break
except:
    print('Please enter a meaningful answer.')
    

只要用户没有输入有意义的答案,while 循环就会运行,但如果输入了有意义的答案,则会中断。




## 解决方案 21:

 
用于`isdigit()`检查字符串是否代表有效的整数。


您可以使用递归函数。


def ask():

answer = input("Please enter amount to convert: ")
if not answer.isdigit():
    print("Invalid")
    return ask()

return int(answer)

Gdp = ask()


或者 while 循环


while True:

answer = input("Please enter amount to convert: ")
if not answer.isdigit():
    print("Invalid")
    continue

Gbp = int(answer)



## 解决方案 22:

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


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


注意:这使用了递归。


相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用