让用户将不同类型的项目输入列表的最佳方法

Best way to get user to input items of different types into a list

在 Python 中提示用户将项目输入到空列表并确保对条目进行评估以纠正数据类型的最佳方式是什么?

例如,用户输入以下 intfloatstrlist 项目值的组合:

24
190.45
'steve'
'steve smith'
['4A', '7B']

new_list 变为 [24, 190.45, 'steve', 'steve smith', ['4A', '7B']]

我尝试了两种方法,每种方法都有重大问题。

方法 1 - 要求用户输入 space 分隔的列表项行,使用 eval() 正确评估和存储数据类型,并使用 str.split() 使用 ' ' 作为分隔符将字符串拆分为组件项:

#  user enters values separated by spaces
input_list = [eval(l) for l in(raw_input('Enter the items for your list separated by spaces: ').split())]
#  check by printing individual items with data type and also complete list
for item in input_list:
    print item, type(item)
print input_list

但是,我知道使用 eval() 从安全角度来看并不好。还使用 ' ' 分隔符进行拆分意味着我无法输入像 'steve smith' 这样的字符串项。但是,我不想让用户输入逗号分隔符等难看的内容。

方法 2 - 使用带有 breakwhile 循环,要求用户输入每个列表项:

input_list = []
while True:
    item = eval(raw_input('Enter new list item (or <Enter> to quit): '))
    if item:
        input_list.append(item)
    else:
        break

同样,我认为应该避免使用 eval()。同时按 Enter 中断会引发 EOF 解析错误,我猜是因为 eval() 无法评估它。

有更好的方法吗?

方法二显然更胜一筹,但需要稍加调整才能避免您看到的错误:

from ast import literal_eval

def get_input_list():
    input_list = []
    while True:
        item = raw_input('Enter new list item (or <Enter> to quit): ')
        if not item:
            break
        input_list.append(literal_eval(item))
    return input_list

请注意,输入 仅在已知为非空时才计算 ,并且使用 ast.literal_eval,这比 [=14] 更安全=],虽然更有限:

The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None.

正在使用:

>>> get_input_list()
Enter new list item (or <Enter> to quit): 24
Enter new list item (or <Enter> to quit): 190.45
Enter new list item (or <Enter> to quit): 'steve'
Enter new list item (or <Enter> to quit): 
[24, 190.45, 'steve']

您还可以添加错误处理,以防用户输入格式错误的字符串或无法评估的内容(例如 'foobar):

try:
    input_list.append(literal_eval(item))
except (SyntaxError, ValueError):
    print "Input not understood. Please try again."