5
\$\begingroup\$

I am in learning process, even though its a very easy project, I still want experts to please review it and share the improvement that can be done, if anyone wants to use other modules to shorten the code then you can also use them, I already thank you to the people who wants to spend their precious time for this. other beginners will also find it helpful.

import pyinputplus as pyp


menu = True

# price of all ingredients
prices = {'wheat': 2, 'white': 1, 'sour dough': 3, 'chicken': 2, 'turkey': 3, 'ham': 2, 'tofu': 1,
          'cheddar': 1, 'swiss': 2, 'mozzarella': 3, 'mayo': 1, 'mustard': 1, 'lettuce': 1,
          'ketchup': 1}
while menu:
    # options to select bread, protein, cheese with inputMenu() method
    bread = pyp.inputMenu(['wheat', 'white', 'sour dough'],
                          prompt='Please select the type of bread you want for your sandwich: \n',
                          numbered=True)

    protein = pyp.inputMenu(['chicken', 'Turkey', 'Ham', 'Tofu'],
                            prompt='Which type of protein you would like: \n',
                            numbered=True)

    cheese = pyp.inputYesNo('Do you want Cheese in your sandwich?(Y/N)\n')
    cheese_type = ''
    if cheese == 'yes':
        cheese_type = pyp.inputMenu(['cheddar', 'swiss', 'mozzarella'], numbered=True)

    # using inputYesNo() for single ingredients with no further types
    mayo = pyp.inputYesNo('Do you want mayo?(Y/N) \n')
    mustard = pyp.inputYesNo('Do you want mustard?(Y/N) \n')
    lettuce = pyp.inputYesNo('Do you want lettuce?(Y/N) \n')
    ketchup = pyp.inputYesNo('Do you want tomato ketchup?(Y/N) \n')

    # using inputInt() and blockRegexes that do not allow negative integer, float or 0
    sandwichQT = pyp.inputInt('How much sandwiches you would like to order?\n',
                              blockRegexes=['[0|-|.]'])

    total_amount = 0

    # using for loop to print items, prices and adding their amount to total_amount variable
    for item, price in prices.items():
        if bread == item:
            print(f'Your sandwich ingredients and prices are as follows: \n'
                  f'{item}= {price}')
            total_amount += price

        if protein == item:
            print(f'{item}= {price}')
            total_amount += price

        if cheese_type == item:
            print(f'{item}= {price}')
            total_amount += price

    # for items that have yes and no values stored and also adding their amount to total
    if mayo == 'yes':
        print(f"mayo = {prices['mayo']}")
        total_amount += prices['mayo']

    if mustard == 'yes':
        print(f"mustard = {prices['mustard']}")
        total_amount += prices['mustard']

    if lettuce == 'yes':
        print(f"lettuce = {prices['lettuce']}")
        total_amount += prices['lettuce']

    if ketchup == 'yes':
        print(f"ketchup = {prices['ketchup']}")
        total_amount += prices['ketchup']

    # at the end printing total amount and how much sandwiches have been ordered
    print(f"sandwich cost x sandwich Qt ordered = {total_amount}x{sandwichQT} = "
          f"{total_amount*sandwichQT}")

    # confirming if the user need to reorder or user wants to confirm the order by simple yes/no
    # if user confirm by typing yes or y then menu will become false and while loop will terminate
    order_confirm = pyp.inputYesNo('Please confirm your order: (Y/N)\n')
    if order_confirm == 'yes':
        print('Please take your order number from the machine and you will be notified when '
              'its ready')
        menu = False
\$\endgroup\$
6
\$\begingroup\$

while True

First of all, using "flag" variables is not customary in Python. Instead of using a boolean variable to control a while loop, you can just do while True: ... break.

Avoiding many ifs

You might notice the repeating structure of:

print(f'{item}= {price}')
total_amount += price

under every if. This is because your logic is reversed. You are currently iterating over ALL possible ingredients and checking if you need them. But there might be many that are not in use. It makes more sense to create a list of ingredients in use and then just take their price in a loop. This will require changing how you save your sauces. Instead of saving them as 'yes', we will save them with their name - to match with the prices dict keys.

So we will create a list of ingredients, and add the sauces as well:

if pyp.inputYesNo('Do you want mayo?(Y/N) \n') == 'yes':
    ingredients.append('mayo')

And now the printing loop will be if-free:

print(f'Your sandwich ingredients and prices are as follows: \n')
for item in ingredients:
    price = prices[item]
    print(f'{item}= {price}')
    total_amount += price

Full Code

import pyinputplus as pyp

# price of all ingredients
prices = {'wheat': 2, 'white': 1, 'sour dough': 3, 'chicken': 2, 'turkey': 3, 'ham': 2, 'tofu': 1,
          'cheddar': 1, 'swiss': 2, 'mozzarella': 3, 'mayo': 1, 'mustard': 1, 'lettuce': 1,
          'ketchup': 1}

while True:
    ingredients = []
    # options to select bread, protein, cheese with inputMenu() method
    ingredients.append(pyp.inputMenu(['wheat', 'white', 'sour dough'],
                          prompt='Please select the type of bread you want for your sandwich: \n',
                          numbered=True))

    ingredients.append(pyp.inputMenu(['chicken', 'Turkey', 'Ham', 'Tofu'],
                            prompt='Which type of protein you would like: \n',
                            numbered=True))

    if pyp.inputYesNo('Do you want Cheese in your sandwich?(Y/N)\n')== 'yes':
        ingredients.append(pyp.inputMenu(['cheddar', 'swiss', 'mozzarella'], numbered=True))

    # using inputYesNo() for single ingredients with no further types
    if pyp.inputYesNo('Do you want mayo?(Y/N) \n') == 'yes':
        ingredients.append('mayo')
    if pyp.inputYesNo('Do you want mustard?(Y/N) \n') == 'yes':
        ingredients.append('mustard')
    if pyp.inputYesNo('Do you want lettuce?(Y/N) \n') == 'yes':
        ingredients.append('lettuce')
    if pyp.inputYesNo('Do you want tomato ketchup?(Y/N) \n') == 'yes':
        ingredients.append('ketchup')

    # using inputInt() and blockRegexes that do not allow negative integer, float or 0
    sandwichQT = pyp.inputInt('How much sandwiches you would like to order?\n',
                              blockRegexes=['[0|-|.]'])

    total_amount = 0
    # using for loop to print items, prices and adding their amount to total_amount variable
    print(f'Your sandwich ingredients and prices are as follows: \n')
    for item in ingredients:
        price = prices[item]
        print(f'{item}= {price}')
        total_amount += price

    # at the end printing total amount and how much sandwiches have been ordered
    print(f"sandwich cost x sandwich Qt ordered = {total_amount}x{sandwichQT} = "
          f"{total_amount*sandwichQT}")

    # confirming if the user need to reorder or user wants to confirm the order by simple yes/no
    # if user confirm by typing yes or y then menu will become false and while loop will terminate
    if pyp.inputYesNo('Please confirm your order: (Y/N)\n')== 'yes':
        print('Please take your order number from the machine and you will be notified when '
              'its ready')
        break
\$\endgroup\$
4
  • \$\begingroup\$ Yup! that was really helpful, your method reduced the coding. I remembered that how If statement slows the program execution, it will not matter in this program but when i was making few games in pygame, a lot of if statements were really giving me low FPS. thanks today i learned 2 new techniques. i never thought i can do this thing: ingredients.append(pyp.inputMenu() i never appended something like this, maybe in list comprehension but not like this. \$\endgroup\$ Nov 10 '20 at 16:23
  • \$\begingroup\$ @MuhammadAhmad I remembered that how If statement slows the program execution, it will not matter in this program but when i was making few games in pygame, a lot of if statements were really giving me low FPS. It's likely a result of what you were computing for each statement, not the baseline performance of the if statements themselves. Are you sure the issue was with the if statements? \$\endgroup\$
    – AMC
    Nov 12 '20 at 19:56
  • \$\begingroup\$ @AMC yeah it was alien invasion i think where I changed the if condition for arrow keys to elif, Before that the spaceship always take 1 sec delay in response to the key i press. But after that i started responding fast, i should not have said the higher FPS because its not related to the frames, it is just the execution of the program. \$\endgroup\$ Nov 16 '20 at 12:05
  • \$\begingroup\$ @MuhammadAhmad How many if statements were there? \$\endgroup\$
    – AMC
    Nov 18 '20 at 1:31

Not the answer you're looking for? Browse other questions tagged or ask your own question.