Hello again! Welcome to part 3 in a series for beginning Python! In Part 2, we covered constants, functions, lists, and string formatting. Today we will be creating a simple order taker using only a few new concepts. If you are completely new to Python, check out Part 1 to start your journey!
Todayâs Topic: Order Taker Bot
Concepts we will learn:
-
Creating multiple functions
-
Sets
-
for loop
-
while loop
-
raising errors
Setup
Just like last time, we are going to start with some introductory code in Programmiz:
MENU = {"soda", "fries", "burger", "shake", "cookie", "chicken strips"}
def main():
pass
if __name__ == "__main__":
main()
Sets
Notice something different with our MENU
constant? Itâs using curly brackets instead of the brackets we used for lists in Part 2! By using curly brackets, and still having comma separated values inside, we are initializing a set. Sets are different from lists in a few ways but most notably, they are faster for searching and can only contain unique values.
Letâs focus on the first difference: searching for a value. With todayâs project, we will be taking an order from your input and checking if what you ordered is actually on the menu. If MENU
was a list, and we ordered a âshakeâ, it would go through the list, checking if soda, fries, burger, and finally shake matched what we ordered. Since MENU
is a set, itâs able to instead check if the hash, or a unique number, of the value is in the set, finding shake immediately.
In less technical terms, a list is the equivalent of having a deck of playing cards face-down, and needing to flip each card over to see if itâs the card you are looking for. A set is the equivalent of having all the cards spread out and face-up, allowing you to quickly find the card you are looking for. This doesnât matter much right now with 6 values but knowing the best data structure for a current task is very important, like whether or not you get hired important.
While Loop
MENU = {"soda", "fries", "burger", "shake", "cookie", "chicken strips"}
def get_order():
current_order = []
while True:
print("What can I get for you?")
order = input()
if order in MENU:
current_order.append(order)
else:
print("I'm sorry, we don't serve that.")
def main():
order = get_order()
if __name__ == "__main__":
main()
Take a look at the new function, get_order()
. The logic is as follows: create an empty list (note the brackets), execute a while loop that is always true, print âwhat can I get for you?â to the console, wait for an input, check if the order is actually on the menu, and if it is then add it to the current order list. If not, print âIâm sorry, we donât serve that.â to the console. What happens after that? The logic starts right back at the top of the while loop! The purpose of a while loop is to continue looping through the same bit of code until the condition of the while loop is no longer true. As you can see, while True:
will never be not true, so we have to find another way out of this loop or risk looping for eternity! Or at least until we close the program.
Naming Conventions
As a quick side note, notice how my functions more or less state the intent of the function in the title? A function ideally is supposed to handle one to two tasks and then return its result, so naming what itâs doing should be fairly easy. In Python, underscores are used to separate words for functions and variables (we will discuss class and object naming later).
Searching
In other languages, there are entire lessons and interview questions devoted to proper searching. Python has them too, just less often due to what you see here: if order_item in MENU:
. If what we ordered is in the MENU constant, then the if
statement is true and our order is added to the current order. Thatâs it, weâve searched the menu and added our order. Alternatively, if we order a banana, we get the response that it isnât served and nothing is added to the current_order
variable.
Escaping the While Loop
In order to escape a while loop, we have 3 options: return
which takes us out of the function, set the condition to False (not possible here since itâs True), or use a new command called break
. There are two new commands in loops that we havenât discussed: continue
and break
. continue
is self explanatory: stop where we are and go back to the top of the loop. break
cuts us out of the loop and allows us to move on in the function, past the while loop. In this project, we are going to make sure we are finished with the order, and return with our current_order
variable. Take a look:
MENU = {"soda", "fries", "burger", "shake", "cookie", "chicken strips"}
def get_order():
current_order = []
while True:
print("What can I get for you?")
order = input()
if order in MENU:
current_order.append(order)
else:
print("I'm sorry, we don't serve that.")
continue
if is_order_complete():
return current_order
def is_order_complete():
print("Anything else? yes/no")
choice = input()
if choice == "no":
return True
elif choice == "yes":
return False
else:
raise Exception("invalid input")
def main():
order = get_order()
if __name__ == "__main__":
main()
A new function has been added called is_order_complete()
and it asks the user if they are finished with their order. If they are, then we return our current order to main()
. If not, then we continue within the while loop. If the user inputs anything other than yes/no, then we raise an error, or essentially flip the table on the program, and exit with the message âinvalid inputâ. Our program doesnât mess around with input handling! Back in get_order()
, we check if is_order_complete()
returned True or False, and return current_order
if so. Notice the continue
right above it? If the user orders something not on the menu, we donât want to ask âis that all?â but instead restart the loop and ask what they want to order.
For Loop
After our user has ordered what they want from the menu, all thatâs needed now is to read back what they ordered and get them to the next window. That means one more function and we are done! Check it out:
MENU = {"soda", "fries", "burger", "shake", "cookie", "chicken strips"}
def get_order():
current_order = []
while True:
print("What can I get for you?")
order = input()
if order in MENU:
current_order.append(order)
else:
print("I'm sorry, we don't serve that.")
continue
if is_order_complete():
return current_order
def is_order_complete():
print("Anything else? yes/no")
choice = input()
if choice == "no":
return True
elif choice == "yes":
return False
else:
raise Exception("invalid input")
def output_order(order_list):
print("Okay, so you want")
for order in order_list:
print(order)
def main():
order = get_order()
output_order(order)
print("Please drive through to the second window.")
if __name__ == "__main__":
main()
Repeating the order
By this point in our program, we have finished getting the order and returned to main()
, having placed our current_order
list into the order
variable. We now have the output_order(order_list)
function to pick up that order, print âOkay, so you wantâ, and print out each item in that order list. If you didnât notice, the variable names between what goes in the function argument and what is used in the function itself do not have to be the same. What is also new is the for loop. A for loop allows us to go through each value in the data structure (list/set/etc), assign the value to a variable, and perform logic on each one individually. This loop is just like the while loop, except that it is constrained to the data structure being looped through, ending once the last value has been read. As you see here, all we do is print each order item, one per line.
What do you mean you donât sell bananas!?
Last, we print out to drive to the next window, and we are done! Feel free to play around with different menu items or extend it to include pricing! How? Dictionaries of course! What are dictionaries? Find out in Part 4. See ya there!