Restaurant Menu System
Clash Royale CLAN TAG#URR8PPP
up vote
7
down vote
favorite
I wrote a basic menu application for my intro to python. I'm fairly new, and python does look promising.
the_burger = 16.99;
french_fries = 5.99;
currie_sauce = 19.99;
napkins_with_chocolates = 10.50;
juice_box = 89.01;
takeout = 18.99;
total = 0.0;
DONE = False
print("""
+-------------------------------------------+
| The Restaurant at the End of the Universe |
+---------------------------------+---------+
| AtThe "Big Boy" Burger | $""" + str(the_burger) + """ |
+---------------------------------+---------+
| BtFrench Fries | $""" + str(french_fries) + """ |
+---------------------------------+---------+
| CtCurrie sauce | $""" + str(currie_sauce) + """ |
+---------------------------------+---------+
| DtNapkins with Chocolates | $""" + str(napkins_with_chocolates) + str(0) + """ |
+---------------------------------+---------+
| EtJuice Box | $""" + str(juice_box) + """ |
+---------------------------------+---------+
| FtTakeout | $""" + str(takeout) + """ |
+---------------------------------+---------+
""");
while(not DONE):
print("Total:", total);
Item = input("Select a letter or 'done': ");
if Item is "A":
total += the_burger;
elif Item is "B":
total += french_fries;
elif Item is "C":
total += currie_sauce;
elif Item is "D":
total += napkins_with_chocolates;
elif Item is "E":
total += juice_box;
elif Item is "F":
total += takeout;
elif Item is "done":
print("Final total:", total);
DONE = True
python python-3.x
 |Â
show 9 more comments
up vote
7
down vote
favorite
I wrote a basic menu application for my intro to python. I'm fairly new, and python does look promising.
the_burger = 16.99;
french_fries = 5.99;
currie_sauce = 19.99;
napkins_with_chocolates = 10.50;
juice_box = 89.01;
takeout = 18.99;
total = 0.0;
DONE = False
print("""
+-------------------------------------------+
| The Restaurant at the End of the Universe |
+---------------------------------+---------+
| AtThe "Big Boy" Burger | $""" + str(the_burger) + """ |
+---------------------------------+---------+
| BtFrench Fries | $""" + str(french_fries) + """ |
+---------------------------------+---------+
| CtCurrie sauce | $""" + str(currie_sauce) + """ |
+---------------------------------+---------+
| DtNapkins with Chocolates | $""" + str(napkins_with_chocolates) + str(0) + """ |
+---------------------------------+---------+
| EtJuice Box | $""" + str(juice_box) + """ |
+---------------------------------+---------+
| FtTakeout | $""" + str(takeout) + """ |
+---------------------------------+---------+
""");
while(not DONE):
print("Total:", total);
Item = input("Select a letter or 'done': ");
if Item is "A":
total += the_burger;
elif Item is "B":
total += french_fries;
elif Item is "C":
total += currie_sauce;
elif Item is "D":
total += napkins_with_chocolates;
elif Item is "E":
total += juice_box;
elif Item is "F":
total += takeout;
elif Item is "done":
print("Final total:", total);
DONE = True
python python-3.x
4
It will let you use Unicode - and probably much more of Unicode than you're already using...
– Toby Speight
19 hours ago
4
Did you ask nicely? (What I mean is, how did you try? And how did it refuse? I know this isn't Stack Overflow, so the non-working code wouldn't be on-topic, but I'd be interested to know).
– Toby Speight
19 hours ago
2
Unicode is supposed to be available out-of-the-box. Example here.
– Mathias Ettinger
18 hours ago
2
Time to use a better IDE then: ideone.com/uK6XJ6
– Mathias Ettinger
17 hours ago
2
I'm not quite sure what the downvote is for... I've followed all of the rules for CR that I can tell.
– FreezePhoenix
16 hours ago
 |Â
show 9 more comments
up vote
7
down vote
favorite
up vote
7
down vote
favorite
I wrote a basic menu application for my intro to python. I'm fairly new, and python does look promising.
the_burger = 16.99;
french_fries = 5.99;
currie_sauce = 19.99;
napkins_with_chocolates = 10.50;
juice_box = 89.01;
takeout = 18.99;
total = 0.0;
DONE = False
print("""
+-------------------------------------------+
| The Restaurant at the End of the Universe |
+---------------------------------+---------+
| AtThe "Big Boy" Burger | $""" + str(the_burger) + """ |
+---------------------------------+---------+
| BtFrench Fries | $""" + str(french_fries) + """ |
+---------------------------------+---------+
| CtCurrie sauce | $""" + str(currie_sauce) + """ |
+---------------------------------+---------+
| DtNapkins with Chocolates | $""" + str(napkins_with_chocolates) + str(0) + """ |
+---------------------------------+---------+
| EtJuice Box | $""" + str(juice_box) + """ |
+---------------------------------+---------+
| FtTakeout | $""" + str(takeout) + """ |
+---------------------------------+---------+
""");
while(not DONE):
print("Total:", total);
Item = input("Select a letter or 'done': ");
if Item is "A":
total += the_burger;
elif Item is "B":
total += french_fries;
elif Item is "C":
total += currie_sauce;
elif Item is "D":
total += napkins_with_chocolates;
elif Item is "E":
total += juice_box;
elif Item is "F":
total += takeout;
elif Item is "done":
print("Final total:", total);
DONE = True
python python-3.x
I wrote a basic menu application for my intro to python. I'm fairly new, and python does look promising.
the_burger = 16.99;
french_fries = 5.99;
currie_sauce = 19.99;
napkins_with_chocolates = 10.50;
juice_box = 89.01;
takeout = 18.99;
total = 0.0;
DONE = False
print("""
+-------------------------------------------+
| The Restaurant at the End of the Universe |
+---------------------------------+---------+
| AtThe "Big Boy" Burger | $""" + str(the_burger) + """ |
+---------------------------------+---------+
| BtFrench Fries | $""" + str(french_fries) + """ |
+---------------------------------+---------+
| CtCurrie sauce | $""" + str(currie_sauce) + """ |
+---------------------------------+---------+
| DtNapkins with Chocolates | $""" + str(napkins_with_chocolates) + str(0) + """ |
+---------------------------------+---------+
| EtJuice Box | $""" + str(juice_box) + """ |
+---------------------------------+---------+
| FtTakeout | $""" + str(takeout) + """ |
+---------------------------------+---------+
""");
while(not DONE):
print("Total:", total);
Item = input("Select a letter or 'done': ");
if Item is "A":
total += the_burger;
elif Item is "B":
total += french_fries;
elif Item is "C":
total += currie_sauce;
elif Item is "D":
total += napkins_with_chocolates;
elif Item is "E":
total += juice_box;
elif Item is "F":
total += takeout;
elif Item is "done":
print("Final total:", total);
DONE = True
python python-3.x
python python-3.x
edited 17 mins ago
asked 19 hours ago


FreezePhoenix
530324
530324
4
It will let you use Unicode - and probably much more of Unicode than you're already using...
– Toby Speight
19 hours ago
4
Did you ask nicely? (What I mean is, how did you try? And how did it refuse? I know this isn't Stack Overflow, so the non-working code wouldn't be on-topic, but I'd be interested to know).
– Toby Speight
19 hours ago
2
Unicode is supposed to be available out-of-the-box. Example here.
– Mathias Ettinger
18 hours ago
2
Time to use a better IDE then: ideone.com/uK6XJ6
– Mathias Ettinger
17 hours ago
2
I'm not quite sure what the downvote is for... I've followed all of the rules for CR that I can tell.
– FreezePhoenix
16 hours ago
 |Â
show 9 more comments
4
It will let you use Unicode - and probably much more of Unicode than you're already using...
– Toby Speight
19 hours ago
4
Did you ask nicely? (What I mean is, how did you try? And how did it refuse? I know this isn't Stack Overflow, so the non-working code wouldn't be on-topic, but I'd be interested to know).
– Toby Speight
19 hours ago
2
Unicode is supposed to be available out-of-the-box. Example here.
– Mathias Ettinger
18 hours ago
2
Time to use a better IDE then: ideone.com/uK6XJ6
– Mathias Ettinger
17 hours ago
2
I'm not quite sure what the downvote is for... I've followed all of the rules for CR that I can tell.
– FreezePhoenix
16 hours ago
4
4
It will let you use Unicode - and probably much more of Unicode than you're already using...
– Toby Speight
19 hours ago
It will let you use Unicode - and probably much more of Unicode than you're already using...
– Toby Speight
19 hours ago
4
4
Did you ask nicely? (What I mean is, how did you try? And how did it refuse? I know this isn't Stack Overflow, so the non-working code wouldn't be on-topic, but I'd be interested to know).
– Toby Speight
19 hours ago
Did you ask nicely? (What I mean is, how did you try? And how did it refuse? I know this isn't Stack Overflow, so the non-working code wouldn't be on-topic, but I'd be interested to know).
– Toby Speight
19 hours ago
2
2
Unicode is supposed to be available out-of-the-box. Example here.
– Mathias Ettinger
18 hours ago
Unicode is supposed to be available out-of-the-box. Example here.
– Mathias Ettinger
18 hours ago
2
2
Time to use a better IDE then: ideone.com/uK6XJ6
– Mathias Ettinger
17 hours ago
Time to use a better IDE then: ideone.com/uK6XJ6
– Mathias Ettinger
17 hours ago
2
2
I'm not quite sure what the downvote is for... I've followed all of the rules for CR that I can tell.
– FreezePhoenix
16 hours ago
I'm not quite sure what the downvote is for... I've followed all of the rules for CR that I can tell.
– FreezePhoenix
16 hours ago
 |Â
show 9 more comments
2 Answers
2
active
oldest
votes
up vote
6
down vote
accepted
Huge bug in 3.5.2
Entering done does nothing in Python 3.5.2, use ==
instead of is
to fix this. In general is
asks if two objects are the same object not if the contents are the same, this can give results different from what you expect for lists, so I suggest using ==
overall.
https://dbader.org/blog/difference-between-is-and-equals-in-python
Code repetition / Extensibility
A famous problem is code extensibility, it is quite inconvenient to add another item to the menu, also if you take a look at this list of if
s
if Item is "A":
total += the_burger;
elif Item is "B":
total += french_fries;
elif Item is "C":
total += currie_sauce;
elif Item is "D":
total += napkins_with_chocolates;
elif Item is "E":
total += juice_box;
elif Item is "F":
you will notice that the only thing that happens is adding the cost to the total each time so there is a lot of repetition.
So let me explain a better solution.
I will use a list
of tuples
(pairs) of the form (food, price).
Than both the printing and the accounting of the money can be done from this data structure, you will only need to add another line inside and both printing and accounting will be generated automatically.
I left out the proper printing alignement as an exercise for the reader, resource: https://stackoverflow.com/questions/5676646/how-can-i-fill-out-a-python-string-with-spaces
Code with didactic comments: (real code would not be commented so much)
# It would be better to import this from string/ascii library
ALPHABET = "ABCDEFGHILMNOPQRSTUVZ"
FOOD_WITH_PRICES = [
("Apple", 0.5),
("Ham", 4),
("Bread", 1)
]
# for x in list: is standard syntax to iterate over a list, x becomes progressively equal to each element
# enumerate adds the index to each element
def print_stilish_menu(food_with_prices):
print("""
+-------------------------------------------+
| The Restaurant at the End of the Universe |
+---------------------------------+---------+""")
for (index, (food, price)) in enumerate(food_with_prices):
print("""
| lettertThe "food" | $ price |
+---------------------------------+---------+
""".format(letter=ALPHABET[index], food=food, price=price))
# list[:n] means the first n elements of a list
# for more info look for `python list slice`
print_stilish_menu(FOOD_WITH_PRICES)
total = 0
while(True):
print("Total:", total);
x = input("Select a letter or 'done': ")
if x in ALPHABET[:len(FOOD_WITH_PRICES)]:
total += FOOD_WITH_PRICES[ALPHABET.index(x)][1]
elif x == 'done':
break
# Some kind of message if the input is invalid
# is good practice
else:
print("Invalid Input")
print("You spent ".format(total))
Yikes, lots of caps. I didn't know that was good practice in python...
– FreezePhoenix
15 hours ago
@FreezePhoenix: All caps names are considered good practice for constants in Python.
– David Foerster
14 hours ago
5
Personally I would replaceALPHABET
withstring.ascii_uppercase
.
– David Foerster
14 hours ago
4
@FreezePhoenix PEP 8, the official style guide for Python, specifies thatALL_CAPS
should be used for constants. Caridorc is doing it correctly. YourDONE
variable, though, is inappropriate.
– 200_success
14 hours ago
add a comment |Â
up vote
8
down vote
Flag variables suck, and should be avoided. Moreover, variables should not be named in ALL_CAPS
to look like constants. All you need to get out of the loop is a break
.
You've hard-coded the parts of the menu in three places:
- the prices
- the ASCII table
- the loop
All of the menu information should be defined in one place. You can programmatically generate the ASCII table using the astropy.io.ascii
package, but I've put together a quick-and-dirty implementation below.
The if
statements in the loop should be replaced by a dictionary lookup. Furthermore, is
is the wrong operator to use; string comparison should be done using ==
. In fact, entering "done" doesn't correctly end the loop, because of that.
You used + str(0)
as a hack to get a price ending in "0" to display properly. To represent fixed-point numbers, you should use a Decimal
instead.
This program is long enough that it would be a good idea to make a main()
function.
Statements should generally not be terminated with semicolons in Python. Also, PEP 8, the official style guide, specifies that indentation should be four spaces. This is an important convention in Python, where indentation matters a lot.
Suggested solution
from collections import OrderedDict, namedtuple
from decimal import Decimal
from string import ascii_uppercase
def tabular(table, widths):
def sandwich(delim, contents):
return delim + delim.join(contents) + delim
def cell(value, width):
return ' ' + str(value).ljust(width - 2)
def cells(row):
return sandwich('|', (cell(col, w) for col, w in zip(row, widths))) + 'n'
horiz_rule = sandwich('+', ('-' * (w - 1) for w in widths)) + 'n'
return sandwich(horiz_rule, (cells(row) for row in table))
# In Python 3.7, this should be a @dataclass instead:
class Item(namedtuple('Item', 'name price')):
def __new__(cls, name, price):
return super().__new__(cls, name, Decimal(price))
def main():
menu_items = OrderedDict(zip(ascii_uppercase, [
Item('The "Big Boy" Burger', '16.99'),
Item('French Fries', '5.99'),
Item('Currie sauce', '19.99'),
Item('Napkins with Chokolates', '10.50'),
Item('Juice Box', '89.01'),
Item('Takeout', '18.99'),
]))
print(
tabular([['The Restaurant at the End of the Universe']], [36 + 9]) +
tabular(
(('0 1.name'.format(*stuff), '$1.price'.format(*stuff))
for stuff in menu_items.items()),
[36, 9]
)
)
total = Decimal('0.00')
while True:
print('Total: $0'.format(total))
selection = input("Select a letter or 'done': ")
if selection == 'done':
break
total += menu_items[selection].price
print('Final total: $0'.format(total))
if __name__ == '__main__':
main()
2
in python 3.6 I would use f-strings instead of str.format and do(f'letter item.name', f'item.price' for letter, item in menu_items.items())
– Maarten Fabré
13 hours ago
1
Also, in Python 3.7+ theOrderedDict
could be a normaldict
.
– Graipher
13 hours ago
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
6
down vote
accepted
Huge bug in 3.5.2
Entering done does nothing in Python 3.5.2, use ==
instead of is
to fix this. In general is
asks if two objects are the same object not if the contents are the same, this can give results different from what you expect for lists, so I suggest using ==
overall.
https://dbader.org/blog/difference-between-is-and-equals-in-python
Code repetition / Extensibility
A famous problem is code extensibility, it is quite inconvenient to add another item to the menu, also if you take a look at this list of if
s
if Item is "A":
total += the_burger;
elif Item is "B":
total += french_fries;
elif Item is "C":
total += currie_sauce;
elif Item is "D":
total += napkins_with_chocolates;
elif Item is "E":
total += juice_box;
elif Item is "F":
you will notice that the only thing that happens is adding the cost to the total each time so there is a lot of repetition.
So let me explain a better solution.
I will use a list
of tuples
(pairs) of the form (food, price).
Than both the printing and the accounting of the money can be done from this data structure, you will only need to add another line inside and both printing and accounting will be generated automatically.
I left out the proper printing alignement as an exercise for the reader, resource: https://stackoverflow.com/questions/5676646/how-can-i-fill-out-a-python-string-with-spaces
Code with didactic comments: (real code would not be commented so much)
# It would be better to import this from string/ascii library
ALPHABET = "ABCDEFGHILMNOPQRSTUVZ"
FOOD_WITH_PRICES = [
("Apple", 0.5),
("Ham", 4),
("Bread", 1)
]
# for x in list: is standard syntax to iterate over a list, x becomes progressively equal to each element
# enumerate adds the index to each element
def print_stilish_menu(food_with_prices):
print("""
+-------------------------------------------+
| The Restaurant at the End of the Universe |
+---------------------------------+---------+""")
for (index, (food, price)) in enumerate(food_with_prices):
print("""
| lettertThe "food" | $ price |
+---------------------------------+---------+
""".format(letter=ALPHABET[index], food=food, price=price))
# list[:n] means the first n elements of a list
# for more info look for `python list slice`
print_stilish_menu(FOOD_WITH_PRICES)
total = 0
while(True):
print("Total:", total);
x = input("Select a letter or 'done': ")
if x in ALPHABET[:len(FOOD_WITH_PRICES)]:
total += FOOD_WITH_PRICES[ALPHABET.index(x)][1]
elif x == 'done':
break
# Some kind of message if the input is invalid
# is good practice
else:
print("Invalid Input")
print("You spent ".format(total))
Yikes, lots of caps. I didn't know that was good practice in python...
– FreezePhoenix
15 hours ago
@FreezePhoenix: All caps names are considered good practice for constants in Python.
– David Foerster
14 hours ago
5
Personally I would replaceALPHABET
withstring.ascii_uppercase
.
– David Foerster
14 hours ago
4
@FreezePhoenix PEP 8, the official style guide for Python, specifies thatALL_CAPS
should be used for constants. Caridorc is doing it correctly. YourDONE
variable, though, is inappropriate.
– 200_success
14 hours ago
add a comment |Â
up vote
6
down vote
accepted
Huge bug in 3.5.2
Entering done does nothing in Python 3.5.2, use ==
instead of is
to fix this. In general is
asks if two objects are the same object not if the contents are the same, this can give results different from what you expect for lists, so I suggest using ==
overall.
https://dbader.org/blog/difference-between-is-and-equals-in-python
Code repetition / Extensibility
A famous problem is code extensibility, it is quite inconvenient to add another item to the menu, also if you take a look at this list of if
s
if Item is "A":
total += the_burger;
elif Item is "B":
total += french_fries;
elif Item is "C":
total += currie_sauce;
elif Item is "D":
total += napkins_with_chocolates;
elif Item is "E":
total += juice_box;
elif Item is "F":
you will notice that the only thing that happens is adding the cost to the total each time so there is a lot of repetition.
So let me explain a better solution.
I will use a list
of tuples
(pairs) of the form (food, price).
Than both the printing and the accounting of the money can be done from this data structure, you will only need to add another line inside and both printing and accounting will be generated automatically.
I left out the proper printing alignement as an exercise for the reader, resource: https://stackoverflow.com/questions/5676646/how-can-i-fill-out-a-python-string-with-spaces
Code with didactic comments: (real code would not be commented so much)
# It would be better to import this from string/ascii library
ALPHABET = "ABCDEFGHILMNOPQRSTUVZ"
FOOD_WITH_PRICES = [
("Apple", 0.5),
("Ham", 4),
("Bread", 1)
]
# for x in list: is standard syntax to iterate over a list, x becomes progressively equal to each element
# enumerate adds the index to each element
def print_stilish_menu(food_with_prices):
print("""
+-------------------------------------------+
| The Restaurant at the End of the Universe |
+---------------------------------+---------+""")
for (index, (food, price)) in enumerate(food_with_prices):
print("""
| lettertThe "food" | $ price |
+---------------------------------+---------+
""".format(letter=ALPHABET[index], food=food, price=price))
# list[:n] means the first n elements of a list
# for more info look for `python list slice`
print_stilish_menu(FOOD_WITH_PRICES)
total = 0
while(True):
print("Total:", total);
x = input("Select a letter or 'done': ")
if x in ALPHABET[:len(FOOD_WITH_PRICES)]:
total += FOOD_WITH_PRICES[ALPHABET.index(x)][1]
elif x == 'done':
break
# Some kind of message if the input is invalid
# is good practice
else:
print("Invalid Input")
print("You spent ".format(total))
Yikes, lots of caps. I didn't know that was good practice in python...
– FreezePhoenix
15 hours ago
@FreezePhoenix: All caps names are considered good practice for constants in Python.
– David Foerster
14 hours ago
5
Personally I would replaceALPHABET
withstring.ascii_uppercase
.
– David Foerster
14 hours ago
4
@FreezePhoenix PEP 8, the official style guide for Python, specifies thatALL_CAPS
should be used for constants. Caridorc is doing it correctly. YourDONE
variable, though, is inappropriate.
– 200_success
14 hours ago
add a comment |Â
up vote
6
down vote
accepted
up vote
6
down vote
accepted
Huge bug in 3.5.2
Entering done does nothing in Python 3.5.2, use ==
instead of is
to fix this. In general is
asks if two objects are the same object not if the contents are the same, this can give results different from what you expect for lists, so I suggest using ==
overall.
https://dbader.org/blog/difference-between-is-and-equals-in-python
Code repetition / Extensibility
A famous problem is code extensibility, it is quite inconvenient to add another item to the menu, also if you take a look at this list of if
s
if Item is "A":
total += the_burger;
elif Item is "B":
total += french_fries;
elif Item is "C":
total += currie_sauce;
elif Item is "D":
total += napkins_with_chocolates;
elif Item is "E":
total += juice_box;
elif Item is "F":
you will notice that the only thing that happens is adding the cost to the total each time so there is a lot of repetition.
So let me explain a better solution.
I will use a list
of tuples
(pairs) of the form (food, price).
Than both the printing and the accounting of the money can be done from this data structure, you will only need to add another line inside and both printing and accounting will be generated automatically.
I left out the proper printing alignement as an exercise for the reader, resource: https://stackoverflow.com/questions/5676646/how-can-i-fill-out-a-python-string-with-spaces
Code with didactic comments: (real code would not be commented so much)
# It would be better to import this from string/ascii library
ALPHABET = "ABCDEFGHILMNOPQRSTUVZ"
FOOD_WITH_PRICES = [
("Apple", 0.5),
("Ham", 4),
("Bread", 1)
]
# for x in list: is standard syntax to iterate over a list, x becomes progressively equal to each element
# enumerate adds the index to each element
def print_stilish_menu(food_with_prices):
print("""
+-------------------------------------------+
| The Restaurant at the End of the Universe |
+---------------------------------+---------+""")
for (index, (food, price)) in enumerate(food_with_prices):
print("""
| lettertThe "food" | $ price |
+---------------------------------+---------+
""".format(letter=ALPHABET[index], food=food, price=price))
# list[:n] means the first n elements of a list
# for more info look for `python list slice`
print_stilish_menu(FOOD_WITH_PRICES)
total = 0
while(True):
print("Total:", total);
x = input("Select a letter or 'done': ")
if x in ALPHABET[:len(FOOD_WITH_PRICES)]:
total += FOOD_WITH_PRICES[ALPHABET.index(x)][1]
elif x == 'done':
break
# Some kind of message if the input is invalid
# is good practice
else:
print("Invalid Input")
print("You spent ".format(total))
Huge bug in 3.5.2
Entering done does nothing in Python 3.5.2, use ==
instead of is
to fix this. In general is
asks if two objects are the same object not if the contents are the same, this can give results different from what you expect for lists, so I suggest using ==
overall.
https://dbader.org/blog/difference-between-is-and-equals-in-python
Code repetition / Extensibility
A famous problem is code extensibility, it is quite inconvenient to add another item to the menu, also if you take a look at this list of if
s
if Item is "A":
total += the_burger;
elif Item is "B":
total += french_fries;
elif Item is "C":
total += currie_sauce;
elif Item is "D":
total += napkins_with_chocolates;
elif Item is "E":
total += juice_box;
elif Item is "F":
you will notice that the only thing that happens is adding the cost to the total each time so there is a lot of repetition.
So let me explain a better solution.
I will use a list
of tuples
(pairs) of the form (food, price).
Than both the printing and the accounting of the money can be done from this data structure, you will only need to add another line inside and both printing and accounting will be generated automatically.
I left out the proper printing alignement as an exercise for the reader, resource: https://stackoverflow.com/questions/5676646/how-can-i-fill-out-a-python-string-with-spaces
Code with didactic comments: (real code would not be commented so much)
# It would be better to import this from string/ascii library
ALPHABET = "ABCDEFGHILMNOPQRSTUVZ"
FOOD_WITH_PRICES = [
("Apple", 0.5),
("Ham", 4),
("Bread", 1)
]
# for x in list: is standard syntax to iterate over a list, x becomes progressively equal to each element
# enumerate adds the index to each element
def print_stilish_menu(food_with_prices):
print("""
+-------------------------------------------+
| The Restaurant at the End of the Universe |
+---------------------------------+---------+""")
for (index, (food, price)) in enumerate(food_with_prices):
print("""
| lettertThe "food" | $ price |
+---------------------------------+---------+
""".format(letter=ALPHABET[index], food=food, price=price))
# list[:n] means the first n elements of a list
# for more info look for `python list slice`
print_stilish_menu(FOOD_WITH_PRICES)
total = 0
while(True):
print("Total:", total);
x = input("Select a letter or 'done': ")
if x in ALPHABET[:len(FOOD_WITH_PRICES)]:
total += FOOD_WITH_PRICES[ALPHABET.index(x)][1]
elif x == 'done':
break
# Some kind of message if the input is invalid
# is good practice
else:
print("Invalid Input")
print("You spent ".format(total))
edited 16 hours ago
answered 16 hours ago
Caridorc
22.8k433113
22.8k433113
Yikes, lots of caps. I didn't know that was good practice in python...
– FreezePhoenix
15 hours ago
@FreezePhoenix: All caps names are considered good practice for constants in Python.
– David Foerster
14 hours ago
5
Personally I would replaceALPHABET
withstring.ascii_uppercase
.
– David Foerster
14 hours ago
4
@FreezePhoenix PEP 8, the official style guide for Python, specifies thatALL_CAPS
should be used for constants. Caridorc is doing it correctly. YourDONE
variable, though, is inappropriate.
– 200_success
14 hours ago
add a comment |Â
Yikes, lots of caps. I didn't know that was good practice in python...
– FreezePhoenix
15 hours ago
@FreezePhoenix: All caps names are considered good practice for constants in Python.
– David Foerster
14 hours ago
5
Personally I would replaceALPHABET
withstring.ascii_uppercase
.
– David Foerster
14 hours ago
4
@FreezePhoenix PEP 8, the official style guide for Python, specifies thatALL_CAPS
should be used for constants. Caridorc is doing it correctly. YourDONE
variable, though, is inappropriate.
– 200_success
14 hours ago
Yikes, lots of caps. I didn't know that was good practice in python...
– FreezePhoenix
15 hours ago
Yikes, lots of caps. I didn't know that was good practice in python...
– FreezePhoenix
15 hours ago
@FreezePhoenix: All caps names are considered good practice for constants in Python.
– David Foerster
14 hours ago
@FreezePhoenix: All caps names are considered good practice for constants in Python.
– David Foerster
14 hours ago
5
5
Personally I would replace
ALPHABET
with string.ascii_uppercase
.– David Foerster
14 hours ago
Personally I would replace
ALPHABET
with string.ascii_uppercase
.– David Foerster
14 hours ago
4
4
@FreezePhoenix PEP 8, the official style guide for Python, specifies that
ALL_CAPS
should be used for constants. Caridorc is doing it correctly. Your DONE
variable, though, is inappropriate.– 200_success
14 hours ago
@FreezePhoenix PEP 8, the official style guide for Python, specifies that
ALL_CAPS
should be used for constants. Caridorc is doing it correctly. Your DONE
variable, though, is inappropriate.– 200_success
14 hours ago
add a comment |Â
up vote
8
down vote
Flag variables suck, and should be avoided. Moreover, variables should not be named in ALL_CAPS
to look like constants. All you need to get out of the loop is a break
.
You've hard-coded the parts of the menu in three places:
- the prices
- the ASCII table
- the loop
All of the menu information should be defined in one place. You can programmatically generate the ASCII table using the astropy.io.ascii
package, but I've put together a quick-and-dirty implementation below.
The if
statements in the loop should be replaced by a dictionary lookup. Furthermore, is
is the wrong operator to use; string comparison should be done using ==
. In fact, entering "done" doesn't correctly end the loop, because of that.
You used + str(0)
as a hack to get a price ending in "0" to display properly. To represent fixed-point numbers, you should use a Decimal
instead.
This program is long enough that it would be a good idea to make a main()
function.
Statements should generally not be terminated with semicolons in Python. Also, PEP 8, the official style guide, specifies that indentation should be four spaces. This is an important convention in Python, where indentation matters a lot.
Suggested solution
from collections import OrderedDict, namedtuple
from decimal import Decimal
from string import ascii_uppercase
def tabular(table, widths):
def sandwich(delim, contents):
return delim + delim.join(contents) + delim
def cell(value, width):
return ' ' + str(value).ljust(width - 2)
def cells(row):
return sandwich('|', (cell(col, w) for col, w in zip(row, widths))) + 'n'
horiz_rule = sandwich('+', ('-' * (w - 1) for w in widths)) + 'n'
return sandwich(horiz_rule, (cells(row) for row in table))
# In Python 3.7, this should be a @dataclass instead:
class Item(namedtuple('Item', 'name price')):
def __new__(cls, name, price):
return super().__new__(cls, name, Decimal(price))
def main():
menu_items = OrderedDict(zip(ascii_uppercase, [
Item('The "Big Boy" Burger', '16.99'),
Item('French Fries', '5.99'),
Item('Currie sauce', '19.99'),
Item('Napkins with Chokolates', '10.50'),
Item('Juice Box', '89.01'),
Item('Takeout', '18.99'),
]))
print(
tabular([['The Restaurant at the End of the Universe']], [36 + 9]) +
tabular(
(('0 1.name'.format(*stuff), '$1.price'.format(*stuff))
for stuff in menu_items.items()),
[36, 9]
)
)
total = Decimal('0.00')
while True:
print('Total: $0'.format(total))
selection = input("Select a letter or 'done': ")
if selection == 'done':
break
total += menu_items[selection].price
print('Final total: $0'.format(total))
if __name__ == '__main__':
main()
2
in python 3.6 I would use f-strings instead of str.format and do(f'letter item.name', f'item.price' for letter, item in menu_items.items())
– Maarten Fabré
13 hours ago
1
Also, in Python 3.7+ theOrderedDict
could be a normaldict
.
– Graipher
13 hours ago
add a comment |Â
up vote
8
down vote
Flag variables suck, and should be avoided. Moreover, variables should not be named in ALL_CAPS
to look like constants. All you need to get out of the loop is a break
.
You've hard-coded the parts of the menu in three places:
- the prices
- the ASCII table
- the loop
All of the menu information should be defined in one place. You can programmatically generate the ASCII table using the astropy.io.ascii
package, but I've put together a quick-and-dirty implementation below.
The if
statements in the loop should be replaced by a dictionary lookup. Furthermore, is
is the wrong operator to use; string comparison should be done using ==
. In fact, entering "done" doesn't correctly end the loop, because of that.
You used + str(0)
as a hack to get a price ending in "0" to display properly. To represent fixed-point numbers, you should use a Decimal
instead.
This program is long enough that it would be a good idea to make a main()
function.
Statements should generally not be terminated with semicolons in Python. Also, PEP 8, the official style guide, specifies that indentation should be four spaces. This is an important convention in Python, where indentation matters a lot.
Suggested solution
from collections import OrderedDict, namedtuple
from decimal import Decimal
from string import ascii_uppercase
def tabular(table, widths):
def sandwich(delim, contents):
return delim + delim.join(contents) + delim
def cell(value, width):
return ' ' + str(value).ljust(width - 2)
def cells(row):
return sandwich('|', (cell(col, w) for col, w in zip(row, widths))) + 'n'
horiz_rule = sandwich('+', ('-' * (w - 1) for w in widths)) + 'n'
return sandwich(horiz_rule, (cells(row) for row in table))
# In Python 3.7, this should be a @dataclass instead:
class Item(namedtuple('Item', 'name price')):
def __new__(cls, name, price):
return super().__new__(cls, name, Decimal(price))
def main():
menu_items = OrderedDict(zip(ascii_uppercase, [
Item('The "Big Boy" Burger', '16.99'),
Item('French Fries', '5.99'),
Item('Currie sauce', '19.99'),
Item('Napkins with Chokolates', '10.50'),
Item('Juice Box', '89.01'),
Item('Takeout', '18.99'),
]))
print(
tabular([['The Restaurant at the End of the Universe']], [36 + 9]) +
tabular(
(('0 1.name'.format(*stuff), '$1.price'.format(*stuff))
for stuff in menu_items.items()),
[36, 9]
)
)
total = Decimal('0.00')
while True:
print('Total: $0'.format(total))
selection = input("Select a letter or 'done': ")
if selection == 'done':
break
total += menu_items[selection].price
print('Final total: $0'.format(total))
if __name__ == '__main__':
main()
2
in python 3.6 I would use f-strings instead of str.format and do(f'letter item.name', f'item.price' for letter, item in menu_items.items())
– Maarten Fabré
13 hours ago
1
Also, in Python 3.7+ theOrderedDict
could be a normaldict
.
– Graipher
13 hours ago
add a comment |Â
up vote
8
down vote
up vote
8
down vote
Flag variables suck, and should be avoided. Moreover, variables should not be named in ALL_CAPS
to look like constants. All you need to get out of the loop is a break
.
You've hard-coded the parts of the menu in three places:
- the prices
- the ASCII table
- the loop
All of the menu information should be defined in one place. You can programmatically generate the ASCII table using the astropy.io.ascii
package, but I've put together a quick-and-dirty implementation below.
The if
statements in the loop should be replaced by a dictionary lookup. Furthermore, is
is the wrong operator to use; string comparison should be done using ==
. In fact, entering "done" doesn't correctly end the loop, because of that.
You used + str(0)
as a hack to get a price ending in "0" to display properly. To represent fixed-point numbers, you should use a Decimal
instead.
This program is long enough that it would be a good idea to make a main()
function.
Statements should generally not be terminated with semicolons in Python. Also, PEP 8, the official style guide, specifies that indentation should be four spaces. This is an important convention in Python, where indentation matters a lot.
Suggested solution
from collections import OrderedDict, namedtuple
from decimal import Decimal
from string import ascii_uppercase
def tabular(table, widths):
def sandwich(delim, contents):
return delim + delim.join(contents) + delim
def cell(value, width):
return ' ' + str(value).ljust(width - 2)
def cells(row):
return sandwich('|', (cell(col, w) for col, w in zip(row, widths))) + 'n'
horiz_rule = sandwich('+', ('-' * (w - 1) for w in widths)) + 'n'
return sandwich(horiz_rule, (cells(row) for row in table))
# In Python 3.7, this should be a @dataclass instead:
class Item(namedtuple('Item', 'name price')):
def __new__(cls, name, price):
return super().__new__(cls, name, Decimal(price))
def main():
menu_items = OrderedDict(zip(ascii_uppercase, [
Item('The "Big Boy" Burger', '16.99'),
Item('French Fries', '5.99'),
Item('Currie sauce', '19.99'),
Item('Napkins with Chokolates', '10.50'),
Item('Juice Box', '89.01'),
Item('Takeout', '18.99'),
]))
print(
tabular([['The Restaurant at the End of the Universe']], [36 + 9]) +
tabular(
(('0 1.name'.format(*stuff), '$1.price'.format(*stuff))
for stuff in menu_items.items()),
[36, 9]
)
)
total = Decimal('0.00')
while True:
print('Total: $0'.format(total))
selection = input("Select a letter or 'done': ")
if selection == 'done':
break
total += menu_items[selection].price
print('Final total: $0'.format(total))
if __name__ == '__main__':
main()
Flag variables suck, and should be avoided. Moreover, variables should not be named in ALL_CAPS
to look like constants. All you need to get out of the loop is a break
.
You've hard-coded the parts of the menu in three places:
- the prices
- the ASCII table
- the loop
All of the menu information should be defined in one place. You can programmatically generate the ASCII table using the astropy.io.ascii
package, but I've put together a quick-and-dirty implementation below.
The if
statements in the loop should be replaced by a dictionary lookup. Furthermore, is
is the wrong operator to use; string comparison should be done using ==
. In fact, entering "done" doesn't correctly end the loop, because of that.
You used + str(0)
as a hack to get a price ending in "0" to display properly. To represent fixed-point numbers, you should use a Decimal
instead.
This program is long enough that it would be a good idea to make a main()
function.
Statements should generally not be terminated with semicolons in Python. Also, PEP 8, the official style guide, specifies that indentation should be four spaces. This is an important convention in Python, where indentation matters a lot.
Suggested solution
from collections import OrderedDict, namedtuple
from decimal import Decimal
from string import ascii_uppercase
def tabular(table, widths):
def sandwich(delim, contents):
return delim + delim.join(contents) + delim
def cell(value, width):
return ' ' + str(value).ljust(width - 2)
def cells(row):
return sandwich('|', (cell(col, w) for col, w in zip(row, widths))) + 'n'
horiz_rule = sandwich('+', ('-' * (w - 1) for w in widths)) + 'n'
return sandwich(horiz_rule, (cells(row) for row in table))
# In Python 3.7, this should be a @dataclass instead:
class Item(namedtuple('Item', 'name price')):
def __new__(cls, name, price):
return super().__new__(cls, name, Decimal(price))
def main():
menu_items = OrderedDict(zip(ascii_uppercase, [
Item('The "Big Boy" Burger', '16.99'),
Item('French Fries', '5.99'),
Item('Currie sauce', '19.99'),
Item('Napkins with Chokolates', '10.50'),
Item('Juice Box', '89.01'),
Item('Takeout', '18.99'),
]))
print(
tabular([['The Restaurant at the End of the Universe']], [36 + 9]) +
tabular(
(('0 1.name'.format(*stuff), '$1.price'.format(*stuff))
for stuff in menu_items.items()),
[36, 9]
)
)
total = Decimal('0.00')
while True:
print('Total: $0'.format(total))
selection = input("Select a letter or 'done': ")
if selection == 'done':
break
total += menu_items[selection].price
print('Final total: $0'.format(total))
if __name__ == '__main__':
main()
edited 14 hours ago
answered 14 hours ago


200_success
125k14145406
125k14145406
2
in python 3.6 I would use f-strings instead of str.format and do(f'letter item.name', f'item.price' for letter, item in menu_items.items())
– Maarten Fabré
13 hours ago
1
Also, in Python 3.7+ theOrderedDict
could be a normaldict
.
– Graipher
13 hours ago
add a comment |Â
2
in python 3.6 I would use f-strings instead of str.format and do(f'letter item.name', f'item.price' for letter, item in menu_items.items())
– Maarten Fabré
13 hours ago
1
Also, in Python 3.7+ theOrderedDict
could be a normaldict
.
– Graipher
13 hours ago
2
2
in python 3.6 I would use f-strings instead of str.format and do
(f'letter item.name', f'item.price' for letter, item in menu_items.items())
– Maarten Fabré
13 hours ago
in python 3.6 I would use f-strings instead of str.format and do
(f'letter item.name', f'item.price' for letter, item in menu_items.items())
– Maarten Fabré
13 hours ago
1
1
Also, in Python 3.7+ the
OrderedDict
could be a normal dict
.– Graipher
13 hours ago
Also, in Python 3.7+ the
OrderedDict
could be a normal dict
.– Graipher
13 hours ago
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f205155%2frestaurant-menu-system%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
4
It will let you use Unicode - and probably much more of Unicode than you're already using...
– Toby Speight
19 hours ago
4
Did you ask nicely? (What I mean is, how did you try? And how did it refuse? I know this isn't Stack Overflow, so the non-working code wouldn't be on-topic, but I'd be interested to know).
– Toby Speight
19 hours ago
2
Unicode is supposed to be available out-of-the-box. Example here.
– Mathias Ettinger
18 hours ago
2
Time to use a better IDE then: ideone.com/uK6XJ6
– Mathias Ettinger
17 hours ago
2
I'm not quite sure what the downvote is for... I've followed all of the rules for CR that I can tell.
– FreezePhoenix
16 hours ago