Python In 30 Days - Day 7
Day seven was about managing inputs and outputs (I/O) via Python.
The Challenge:
Extend your Restaurant class with file I/O capabilities:
1. Add a method save_order(self, filename) that:
- Writes the restaurant name to the first line
- Writes each item in
self.orderon its own line - Writes the total on the last line, formatted as "Total: $X"
- Prints a confirmation when saved
2. Add a method load_order(self, filename) that:
- Reads the file back in
- Reconstructs
self.orderfrom the saved items (skip the restaurant name line and the total line) - Prints a confirmation showing how many items were loaded
- Handles the case where the file doesn't exist gracefully (there's a specific exception for this — find it)
3. Create a Restaurant instance, add some items, save the order to a file, then create a fresh instance of the same restaurant with an empty order and load the file into it — proving the persistence works
4. Print the order and total both before saving and after loading to show they match
Things to figure out: how to strip the "\n" off lines when reading back in, which exception fires when a file doesn't exist, and how to skip the first and last lines of a list.
My Code:
class Restaurant:
def __init__(self, name, menu):
self.name = name
self.menu = menu
self.order = []
def add_item(self, item_name):
try:
price = self.menu[item_name]
except TypeError:
print(f"Sorry, {item_name} is not a string.\n")
except KeyError:
print(f"Sorry, {item_name} is not on the menu!\n")
else:
self.order.append(item_name)
# print(f"Added {item_name} to order.")
def print_order(self):
print("\nYour Order:")
print(*self.order, sep="\n")
def get_total(self):
if not self.order:
print("\nWarning: Your order is empty.\n")
return 0
total = 0
for i in self.order:
try:
total += self.menu[i]
except KeyError:
print(f"Warning: {i} is not on the menu. Skipping item.")
return total
def __str__(self):
menu_len = len(self.menu)
order_len = len(self.order)
return f"{self.name} | Menu Items: {menu_len} | Current Order: {order_len}"
def save_order(self, filename):
with open(f"{filename}", "w") as f:
f.write(f"{self.name}\n")
for item in self.order:
f.write(f"{item}\n")
f.write(f"Total: ${self.get_total()}")
print(f"Order Saved to {filename}")
def load_order(self, filename):
try:
with open(f"{filename}", "r") as f:
lines = f.read().splitlines()
self.order = lines[1:-1]
order_len = len(self.order)
print(f"Loaded {order_len} items")
except FileNotFoundError:
print(f"Sorry, {filename} not found.")
mario = Restaurant(
"Mario's Restaurant",
{"Pizza": 12, "Breadsticks": 8, "Salad": 6, "Tiramisu": 4, "Wine": 18},
)
mario.add_item("Pizza")
mario.add_item("Tiramisu")
mario.print_order()
mario_total = mario.get_total()
print(f"Your total is: ${mario_total}")
mario.save_order("order.txt")
new_mario = Restaurant(
"Mario's Restaurant",
{"Pizza": 12, "Breadsticks": 8, "Salad": 6, "Tiramisu": 4, "Wine": 18},
)
new_mario.load_order("order.txt")
new_total = new_mario.get_total()
new_mario.print_order()
print(f"Your total is: ${new_total}")
Running the Code:
Your Order:
Pizza
Tiramisu
Your total is: $16
Order Saved to order.txt
Loaded 2 items
Your Order:
Pizza
Tiramisu
Your total is: $16
As you can see, the code works as expected. mario is the first instance of the Restaurant class and new_mario is a brand new instance of the class. I was able to build the order for mario and then print the order items in a human readable way, then write those to a file called order.txt.
After that the code reads the order.txt file and skips the first and last lines, then removes the trailing \n from each of the items in the list. We then call the load_order method on new_mario and are able to print the order and total once again in a human readable way.