Reputation: 17
Yesterday I posted a question about a grocery list and recieved a lot of help with it. I have encountered another problem with it. Here is my code:
item = {}
while True:
x = input('enter item: ')
if x =='done':
break
y = float(input('enter price: '))
item[x] = (y)
slist = {}
print('How much do you want of everything?')
while True:
listitem = input("Item name: ")
if listitem == 'done':
break
qty = float(input("How many: "))
slist[listitem] = qty
total = 0
for key in item:
value = item[key] * slist[key]
total = total + value
print(total)
The problem comes when you input an item for the first loop and then don't input it for the second one. For example, putting in: Milk, 5 - Eggs, 3 - Bread, 2, into the first loop and then only including Milk and Eggs for the second loop results in an error:
Traceback (most recent call last):
File "V:\Downloads\grocery list.py", line 24, in <module>
value = item[key] * slist[key]
KeyError: 'Bread'
What can I do to prevent this from happening?
Upvotes: 1
Views: 736
Reputation: 78760
Instead of looping
for key in item
you should be doing
for key in slist
since item
contains all items in the store and slist
only the purchased items.
slist
is a bad name by the way, it's a dictionary, not a list.
Demo with adjusted code:
enter item: Milk
enter price: 5
enter item: Eggs
enter price: 3
enter item: Bread
enter price: 2
enter item: done
How much do you want of everything?
Item name: Milk
How many: 2
Item name: Eggs
How many: 1
Item name: done
13.0
Upvotes: 1
Reputation: 155516
Change:
value = item[key] * slist[key]
to:
value = item[key] * slist.get(key, 0)
dict.get
is used when you want to get a value if it exists, or get a default value otherwise. That makes it so, if slist
doesn't contain key
(you didn't actually want that item), you treat it as having a count of 0 (if it does have the key
, the default 0
is ignored).
Alternatively, flip your loop to loop over the shopping list (for key in slist:
) rather than the inventory, and leave the calculation unchanged. In that case, you want the exception; if your shopping list contains an item that isn't in the store, you want the attempt to look up its price to fail.
Side-note: Not necessary for correctness, but if you're using both the key and the value, it's easier to iterate them both in parallel, rather than just iterating keys, and looking up the value later. It also lets you provide more useful names so the code self-documents. The loop could be changed to (for example):
for listitem, wanted in slist.items():
value = item[listitem] * wanted
total += value
avoiding repeated lookup and making the intent more clear.
Upvotes: 1