2

我正在通过制作小程序来学习 Python(以及一般的编程)。下面是一个基本的购物程序,它将根据所选食物返回要购买的物品列表。

我想改进它并允许用户一次选择几种食物(例如用户输入将是“1、2、3”)并基于此返回一个成分列表。

我应该采取什么样的方法?我正在使用 Python 2.7,这是我现有的代码:

mm_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:"
print "1. Minced Meat Soup"
print "2. Sunday Soup"
print "3. Gulas"

choose = raw_input("> ")

if choose == '1':
    print "Buy", ", ".join(mm_soup) + "." 

elif choose == '2':
    print "Buy", ", ".join(sunday_soup) + "."

elif choose == '3':
    print "Buy", ", ".join(gulas) + "."

else:
    print "Hmmm. No such food on the list."
4

2 回答 2

8

您的代码存在一些常见问题,因此让我们从修复这些问题开始。

您有多个要呈现给用户的项目,并且您正在对这些值进行硬编码。这会为您带来很多努力,因为您必须经常重复自己。看看你的选择线,它们基本上都是一样的。您还可以通过在描述和代码中定义数字链接到的内容来重复自己。让我们尝试用数据结构来简化它。

在这里,我们列出所有选项 - 元组列表,定义给定食物的名称和项目集。我们在这里使用一套,因为我们不需要订购这些物品。

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),但这是基本思想。

于 2012-05-28T19:53:13.680 回答
1

我想您可以拆分输入的字符串并遍历其元素:

choose = raw_input("> ")
for choice in choose.split(', '): #split by comma and space
    if choice == '1':
        print "Buy", ", ".join(mm_soup) + "." 
    elif choice == '2':
        print "Buy", ", ".join(sunday_soup) + "."    
    elif choice == '3':
        print "Buy", ", ".join(gulas) + "."
    else:
        print "Hmmm. No such food on the list."

或类似的东西:

choose = raw_input("> ");
selected = choose.split(', ') #split by comma and space

suggestion = '';
if '1' in selected :
    suggestion += ", ".join(mm_soup)
if '2' in selected :
    suggestion += ", ".join(sunday_soup)
if '3' in selected :
    suggestion += ", ".join(gulas)

if len(suggestion) > 0:
    print "Buy " + suggestion + "."
else:
    print "Hmmm. No such food on the list."
于 2012-05-28T19:28:29.143 回答