Python中的购物清单

时间:2012-05-28 19:22:12

标签: python

我正在通过制作小程序来学习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."

2 个答案:

答案 0 :(得分:7)

您的代码存在一些常见问题,因此我们首先修复这些问题。

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

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

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

请注意the enumerate() builtin的使用,以便为我们提供选项的编号。当你想从1开始,而Python正常从0开始计算时,我们也会传递它。

这为我们提供了输出,但我们现在可以轻松添加更多项目而无需修改现有代码。我们像以前一样问,然后我们可以简单地从列表中获取他们给我们的索引,而不是加载if / elif s。我们首先要将字符串更改为数字,然后取出一个(因为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有一些内置的功能来构建列表 - list comprehensions。我们可以这样做:

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

答案 1 :(得分: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."