您的代码存在一些常见问题,因此让我们从修复这些问题开始。
您有多个要呈现给用户的项目,并且您正在对这些值进行硬编码。这会为您带来很多努力,因为您必须经常重复自己。看看你的选择线,它们基本上都是一样的。您还可以通过在描述和代码中定义数字链接到的内容来重复自己。让我们尝试用数据结构来简化它。
在这里,我们列出所有选项 - 元组列表,定义给定食物的名称和项目集。我们在这里使用一套,因为我们不需要订购这些物品。
options = [
("Minced Meat Soup", {'minced meat', 'potatoes', 'frozen vegetable'}),
("Sunday Soup", {'chicken with bones', 'noodles', 'soup vegetable'}),
("Gulas", {'pork meat', 'food cream', 'potatoes', 'onion', 'frozen peas'}),
]
这为我们提供了一个良好的数据结构。
然后我们可以提出我们的问题,而不是手动构建它,我们可以使用循环从我们的选项列表中构建它:
print "What would you like to cook on weekend?"
print "Here are the options:"
for option, (name, values) in enumerate(options, 1):
print str(option)+". "+name
请注意内置函数的enumerate()
使用,以便为我们提供选项的数字。由于您想从 1 开始,而 Python 通常从 0 开始计数,因此我们也将其传入。
这为我们提供了输出,但我们现在可以轻松添加更多项目,而无需修改现有代码。我们像以前一样询问,然后我们可以简单地从列表中获取它们给我们的索引,而不是加载if
/ s。elif
我们首先必须将字符串更改为一个数字,然后取出一个(因为 Python 从 0 开始计数)。这给了我们:
_, values = options[int(choose)-1]
(使用元组解包忽略第一个值,因为它是我们不需要的名称)。
现在唯一的问题是,例如,如果用户输入超出范围的数字或单词,将会发生什么。您可以在转换为 int 并使用它之前对其进行检查,但是简单地尝试它是 Pythonic,并在失败时捕获抛出的异常。例如:
try:
_, values = options[int(choose)-1]
print "Buy", ", ".join(values) + "."
except (IndexError, ValueError):
print "Hmmm. No such food on the list."
这使得整个程序变得更小,并且还要注意添加新项目是多么容易,您只需将它们添加到列表中即可。
那么我们如何处理多个项目呢?嗯,现在也很简单。我们可以获取用户的输入,用逗号分隔,然后删除值以删除任何空格,然后执行与之前相同的操作:
for choice in choose.split(","):
choice = choice.strip()
try:
_, values = options[int(choice)-1]
print "Buy", ", ".join(values) + "."
except (IndexError, ValueError):
print "Hmmm. No such food on the list."
这很有效,可以打印出多条购买行,但这不是最佳选择,更好的主意是生成一个更大的购物清单,其中包含所有需要的物品。
我们可以通过在循环时构建一组所有项目,然后打印出该集合来构建它。
shopping_list = []
for choice in choose.split(","):
choice = choice.strip()
try:
_, values = options[int(choice)-1]
shopping_list.append(values)
except (IndexError, ValueError):
print "Hmmm. No such food on the list."
然而,这有点低效和丑陋。Python 有一些内置功能来构建列表-列表推导。我们可以这样操作:
try:
shopping_list = [options[int(choice.strip())-1][3] for choice in choose.split(",")]
except (IndexError, ValueError):
print "Hmmm. No such food on the list."
现在我们需要打印出列表中的所有值。请记住,这是一个集合列表,因此", ".join()
不会完全按照我们的意愿行事。我们在这里有两个选择。我们可以使用生成器表达式先连接集合,然后连接连接的字符串:
print "Buy " + ", ".join(", ".join(values) for values in shopping_list) + "."
或者,我们可以itertools.chain.from_iterable()
用来返回一个扁平化的迭代器:
print "Buy " + ", ".join(itertools.chain.from_iterable(shopping_list)) + "."
这给了我们:
import itertools
options = [
("Minced Meat Soup", {'minced meat', 'potatoes', 'frozen vegetable'}),
("Sunday Soup", {'chicken with bones', 'noodles', 'soup vegetable'}),
("Gulas", {'pork meat', 'food cream', 'potatoes', 'onion', 'frozen peas'}),
]
print "What would you like to cook on weekend?"
print "Here are the options:"
for option, (name, values) in enumerate(options, 1):
print str(option)+". "+name
choose = raw_input("> ")
try:
shopping_list = [options[int(choice.strip())-1][1] for choice in choose.split(",")]
print "Buy " + ", ".join(itertools.chain.from_iterable(shopping_list)) + "."
except (IndexError, ValueError):
print "Hmmm. No such food on the list."
这会产生类似的东西:
What would you like to cook on weekend?
Here are the options:
1. Minced Meat Soup
2. Sunday Soup
3. Gulas
> 1, 2
Buy potatoes, frozen vegetable, minced meat, chicken with bones, noodles, soup vegetable.
这很短,易于扩展,并且运行良好。您还可以处理一些其他问题(您想如何处理多个相同的项目?您可能需要对此进行研究collections.Counter
),但这是基本思想。