Avoid break
and continue
if possible
Because they alter the control flow and may complicate the code.
while True:
# Stuff in the middle...
more_items = (input("Do you want to order more items?")).lower()
if more_items == "yes":
pass
else:
break
is better written as
more_items = "yes"
while more_items == "yes":
# Stuff in the middle...
more_items = (input("Do you want to order more items?")).lower()
pass
does nothing so you (usually) don't need them
To mark a section where more code will be added in the future, a # TODO:
comment conveys the intent better.
Avoid code duplication if the duplication is undesirable
The conditionals in
if choice == "BIG MAC":
processOrder(quantity, A[0])
elif choice == "LARGE FRIES":
processOrder(quantity, A[1])
elif choice == "VEGETARIAN BURGER":
processOrder(quantity, A[2])
just repeats the same test in a loop
for i in range(len(A)):
if choice == A[i][0].upper()
processOrder(quantity, A[i])
Always verify user input unless failure is an option
choice, quantity = (input("\nWhat would you like?\n")).upper(), int(input("\nHow many would you like?\n"))
can fail if the user inputs a non-numeric answer; also, nothing prevents the user from giving a negative (or floating) number for the quantity, which is likely not what you want.
I've implemented my own version of the program for fun and practice, as shown at the end. This assumes one cashier at one McDonald's. If you want to support more than one instance of this program running, perhaps use a relational database to do the constraint checking instead and handle the race conditions. You can start by looking at the sqlite3
package.
Taking up on jrtapsell's "Storing food items" point, I've crafted a mutable version of namedtuple
to better represent variable quantities such as price and stock, because namedtuple
, as the name suggests, is a tuple and therefore is immutable. The program also accepts numbered response for the choice so you don't have to type out the name. I used capwords
because, well, lazy.
#!/usr/bin/env python
import collections
from string import capwords
def foodplan(price, stock):
if not str(stock).isdecimal():
raise ValueError("Can only assign a whole number to stock attribute")
return type('FoodPlan', (object,), dict(price=float(price), stock=int(stock)))
def get_choice():
while True:
option = input("What would you like? ")
if option.isdecimal() and 0 <= int(option) - 1 < len(choices):
return list(choices.keys())[int(option) - 1]
elif capwords(option) in choices.keys():
return capwords(option)
else:
print("Invalid item")
def get_quantity(choice):
while True:
quantity = input("How many would you like? ")
if quantity.isdecimal():
if int(quantity) <= choices[choice].stock:
return int(quantity)
else:
print("There is not enough stock!")
else:
print("Illegal quantity")
choices = collections.OrderedDict({
"Big Mac": foodplan(2.50, 50),
"Large Fries": foodplan(0.50, 200),
"Vegetarian Burger": foodplan(1.00, 20),
})
if __name__ == '__main__':
orders = dict(zip(choices.keys(), [0] * len(choices)))
print("Welcome to McDonald's")
ordering = 'y'
while ordering == 'y':
[print("{0}. {1}, £{2}".format(
i + 1, list(choices.keys())[i], list(choices.values())[i].price
)) for i in range(len(choices))]
choice = get_choice()
quantity = get_quantity(choice)
orders[choice] += quantity
choices[choice].stock -= quantity
ordering = input("Do you want to order more items? [y/*] ").lower()
print("\nThank you for ordering!\nYour total cost is: £{0}".format(
sum([orders[choice] * choices[choice].price
for choice in choices.keys()])
))
A[1]
three times for the menu. Shouldn't that be each member ofA
once? \$\endgroup\$