Hopefully my code and question(s) are clear for understanding. If they are not please provide feed back.
I am fairly new to programing/coding so I decided to develop a program using Python that acts like a pizza ordering system. I eventually would like to use this code to develop a website using Django or Flask.
I have just finished the first step of this program where I am asking the user if this will be for delivery of pickup. Depending on what the user chooses the program will ask for specific information.
The area I feel like I am struggling with the most is developing classes and functions. specifically taking a variables from one function and using that variable in another function. I posted a past example of my code and I was advised that Global variables are not good to use in code. So I am trying really hard to refrain from using them.
Here is the code for reference:
import re
running = True
class PizzaOrderingSys():
"""order a customized pizza for take out or delivery """
def delivery_or_pickup(self): # Is the order for devilery or pickup?
print("\nWill this order be for pickup or delivery?")
self.delivery = input("P - pick up / D - delivery : ")
self.delivery = self.delivery.title()
if self.delivery == "D":
while running == True:
customerName = input("\nName for the order: ")
if not re.match("^[a-zA-Z ]*$", customerName):
print("Please use letters only")
elif len(customerName) == 0:
print("Please enter a vaild input")
else:
customerName = customerName.title()
break
while running == True:
customerPhoneNumber = input("\nEnter a phone number we can contact you at: ")
if not re.match("^[0-9 ]*$", customerPhoneNumber):
print("Please use numbers only")
elif len(customerPhoneNumber) == 0:
print("Please enter a a contact phone number")
else:
break
while running == True:
house_num = input("\nWhat is your house or unit number: ")
if not re.match("^[0-9 /]*$", house_num):
print("Please use numbers only")
elif len(house_num) == 0:
print("Please enter a valid input ")
else:
break
while running == True:
streetName = input("\nStreet name: ")
if not re.match("^[a-zA-Z ]*$", streetName):
print('Please use letters only.')
elif len(streetName) == 0:
print("Please enter a valid input")
else:
streetName = streetName.title()
break
while running == True:
city = input("\nCity: ")
if not re.match("^[a-zA-Z ]*$", city):
print("Please use letters only")
elif len(city) == 0:
print("Please enter a valid input")
else:
city = city.title()
break
while running == True:
zip_code = input("\nZip Code:")
if not re.match("^[0-9 /]*$", zip_code):
print("Please use numbers only")
elif len(zip_code) == 0 or len(zip_code) > 5:
print("Please enter a valid input")
else:
break
elif self.delivery == "P":
while running == True:
customerName = input("\nName for the order: ")
if not re.match("^[a-zA-Z ]*$", customerName):
print("Please use letters only")
elif len(customerName) == 0:
print("Please enter a valid input")
else:
customerName = customerName.title()
break
while running == True:
customerPhoneNumber = input("\nEnter a phone number we can contact you at: ")
if not re.match("^[0-9 ]*$", customerPhoneNumber):
print("Please use numbers only")
elif len(customerPhoneNumber) == 0:
print("Please enter a valid input")
else:
break
else:
print("Please enter P or D ")
delivery_or_pickup()
order = PizzaOrderingSys()
order.delivery_or_pickup()
My question is this: How would I use variables found in one function of my class and use it in another future function??
For example if I wanted to retrieve variables the functions customerName, customerPhoneNumber, house_num, streetName, city, Zip_code found in delivery_or_pick() function and use them in a function called:
def customer_receipt():
What would I need to do to my exiting code or to the def customer_receipt() function to obtain that information?
Any help with my questions or advise on any other area that stick out to you would be be greatly appropriated.
This is my second post on Stackoverflow so I apologize if what i am asking is unclear or the format of my question might is off, I am still learning.
Thank you again.
The idea here is that you can use your class variables to save data between method calls. Methods are functions that belong to a class. For example you could use Python's class initialization and create a dict of orders. Here is a simple example of such system, take a note of the usage of self keyword. self refers to the instance of the class and you can use it to access the variables or methods of the instance:
class PizzaOrderingSys:
def __init__(self):
# Initializing some class variables
self.running = True # Now you can use self.running instead of global running variable
self.orders = {}
def delivery_or_pickup(self):
# Somewhere at the end where you have collected the needed info
order = {
"zip_code": zip_code,
"city": city,
# You can enter all of the needed data similarly
}
order_id = "SomeIdHere" # ID could be anything, it just should be unique
self.orders[order_id] = order
return order_id
def customer_receipt(self, id):
# Now you can access all of the order here with self.orders
order = self.orders.get(id) # Select some specific order with id.
# Using get to avoid the situation
# where no orders or invalid id would raise an exception
if order:
receipt = f"Order {id}:\nCustomer city {order['city']}"
else:
receipt = None
return receipt
pizzasystem = PizzaOrderingSys()
order_id = pizzasystem.delivery_or_pickup()
receipt = pizzasystem.customer_receipt(order_id)
print(receipt)
# >>> Order 1235613:
# Customer city Atlantis
I recommend that you read more about classes, for example, python docs have great material about them.
Related
I am fairly new to Python/programming, I started about four months ago and since I am a teacher and may possible have a lot more time on my hands.
For my first project I have started to develop a pizza ordering system-- at the moment I am just having the user interact with the program through the terminal. However, I plan to evidentially use Django to create a web page so a user can actually interact with.
I will first share my code:
import re
sizePrice = {
'small': 9.69,
'large': 12.29,
'extra large': 13.79,
'party size': 26.49 }
toppingList = [ 'Anchovies', 'Bacon', 'Bell Peppers', 'Black Olives',
'Chicken', 'Ground Beef', 'Jalapenos', 'Mushrooms',
'Pepperoni','Pineapple', 'Spinach']
pickupCost = 0 deliveryCost = 5.0
running = True
def pick_or_delivery():
global delivery
print('\nWill this be for pick up or delivery?')
delivery = input("P - pick up / D - delivery")
delivery = delivery.title() # changes the letter inputted to an upper case.
print(f'This order will be for {delivery}')
if delivery == "D":
while running == True:
global customerName
customerName = input("\nName for the order: ")
if not re.match("^[a-zA-Z ]*$", customerName):
print("Please use letters only")
elif len(customerName) == 0:
print("Please enter a vaild input")
else:
customerName = customerName.title()
break
while running == True:
global customerPhoneNumber
customerPhoneNumber = input("\nEnter a phone number we can contact you at: ")
if not re.match("^[0-9 ]*$", customerPhoneNumber):
print("Please use numbers only")
elif len(customerPhoneNumber) == 0:
print("Please enter a a contact phone number")
else:
break
while running == True:
global streetName
streetName = input("Street name: ")
if not re.match("^[a-zA-Z ]*$", streetName):
print('Please use letters only.')
elif len(streetName) == 0:
print("Please enter a valid input")
else:
streetName = streetName.title()
break
elif delivery == "P":
while running == True:
global customerName
customerName = input("\nName for the order: ")
if not re.match("^[a-zA-Z ]*$", customerName):
print("Please use letters only")
elif len(customerName) == 0:
print("Please enter a valid input")
else:
print("Please enter P or D")
customerName = customerName.title()
break
while running == True:
global customerPhoneNumber
customerPhoneNumber = input("\nEnter a phone number we can contact you at: ")
customerName = customerName.title()
if not re.match("^[0-9 ]*$", customer_telephone):
print("Please use numbers only")
elif len(customer_telephone) == 0:
print("Please enter a valid input")
else:
break
else:
print("Please enter P or D ")
pick_or_delivery()
pick_or_delivery()
When I run this code I receive the following:
SyntaxError: name 'customerName' is used prior to global declaration
I know the issue is in my global variables, however in my code I am placing the global variable before it is being called. So I am a little confused. Is the placement incorrect? If so, where should it go?
I think it is because you have globalised customerName within your if statements. Try and create a variable called customerName at the start of your function and give it a blank value, then globalise it at the start of your function.
How do I correctly define and call these functions?
I am trying to build an application that will prompt the main menu, go through a logon process, go to the next function, which would be the login menu and reference the inputs from the logon function so users do not have to input their card number and pin twice.
The issue I'm having is trying to be able to reference a variable in my second function, which is located in the same class. I'm being told by coworkers that using globals is bad and I shouldn't. Here is the code.
I've taken out some things as they aren't really important. I'd like to, for instance, use the elif choice ==3 statement to reference the original one_row.
p.s. I have changed def Login(self) to include the variables I'd like to reference, but then my main menu complains that the inputs have not been defined yet.
class LoginPrompt:
def Login(self):
while True:
print(menu[1])
self.Card_number=str(input('>> '))
print(menu[2])
self.Character_PINs = getpass.getpass('>> ')
self.one_row = c.execute('SELECT * FROM {tn} WHERE {cn}=? and {cnn}=?'.\
format(tn=table_1, cn=column_1, cnn=column_3), (self.Character_PINs, self.Card_number,))
for row in self.one_row.fetchone():
print('Welcome: ', row)
return
else:
print('PIN incorrect; try again')
def loginMenu(self):
while True:
print(menu[5])
print("\n1 - Deposit funds")
print("2 - Withdraw funds")
print("3 - Check balance")
print("4 - Reset Pin")
print("5 - Exit")
while True:
try:
choice = int(input("Please enter a number: "))
except ValueError:
print("This is not a number")
if choice >= 1 and choice <=5:
if choice == 1:
amount = input("\nPlease enter the deposit amount: ")
if amount != '' and amount.isdigit():
int(amount)
amount = c.execute('UPDATE {tn} SET Balances = ? WHERE {cn}=?'.\
format(tn=table_1, cn=column_2), (amount,))
else:
print("Please enter a valid number")
conn.commit()
conn.close
elif choice ==3:
print(Login.one_row)
elif choice ==5:
input('Enjoy your stay, and always remember to drink Nuka Cola! ')
return(mainMenu)
else:
return
def mainMenu():
print(menu[0])
chosen=False
while not chosen:
opt=int(input('\n Please choose one of the options below:\n\n-> Register for a new account [1]\n-> Login to an existing account [2]\n\nPlease type a number...\n\n>> '))
if opt==1:
userReg()
chosen=True
elif opt==2:
login_Menu = LoginPrompt()
login_Menu.Login()
chosen=True
login_Menu.loginMenu()
else:
print('\n\nPLEASE TYPE EITHER 1 OR 2...\n ')
print(chosen)
if __name__ == "__main__":
while True:
mainMenu()
Here, you instantiated a single instance of LoginPrompt and called Login and loginMenu on it:
login_Menu = LoginPrompt()
login_Menu.Login()
...
login_Menu.loginMenu()
Since you assign an instance variable self.one_row in Login, you can access the same instance variable via self.one_row in loginMenu:
class LoginPrompt:
def Login(self):
while True:
...
self.one_row = ...
...
def loginMenu(self):
while True:
...
while True:
...
if choice >= 1 and choice <=5:
...
elif choice == 3:
# print(Login.one_row)
print(self.one_row)
You can read more about self and instance variables in the Python documentation: https://docs.python.org/3.8/tutorial/classes.html#class-and-instance-variables
A note about code style
In Python, the convention is to:
name functions consistently in lower_case_with_underscores (and classes in CapWords), and
name instances after the class name.
login_prompt = LoginPrompt()
login_prompt.login()
...
login_prompt.login_menu()
You can read more about naming conventions in the PEP 8 style guide for Python code: https://www.python.org/dev/peps/pep-0008/#prescriptive-naming-conventions
I have a problem in which users can input spaces or nothing and still pass through the program, how do I go about preventing this? I am still a beginner at python.
def orderFunction(): # The function which allows the customer to choose delivery or pickup
global deliveryPickup
deliveryPickup = input("Please input delivery or pickup: d for delivery p for pickup")
if deliveryPickup == "d":
global customerName
while True:
try:
customerName = (input("Please input your name"))
if customerName == (""):
print("Please input a valid name")
else:
break
global customerAddress
while True:
try:
customerAddress = (input("Please input your name"))
if customerAddress == (""):
print("Please input a valid Address")
else:
break
global customerPhnum
while True:
try:
customerPhnum = int(input("Please input your phone number"))
except ValueError:
print("Please input a valid phone number")
else:
break
print("There will also be a $3 delivery surcharge")
elif deliveryPickup == "p":
customerName = (input("Please input your name"))
if customerName == (""):
print("Please input a valid name")
orderFunction()
else:
print("Please ensure that you have chosen d for Delivery or p for Pickup")
orderFunction()
orderFunction()
Here is my attempt at doing this but I get all kinds of unindent and indent errors at the moment and I think my while loops are probably wrong.
Essentially if I input a space or hit enter into one of the customer inputs (customerName for instance) it gets stored. This needs to prevented and I have tried to fix it by using while loops which obviously haven't worked.
Hopefully someone has a solution to this problem
Many Thanks.
.strip() removes all tabs or spaces before and after a string.
Meaning all spaces == empty string. All tabs == empty string. So all you have to check if the length of that string != 0 or the string is not empty. Just use an infinite loop to keep on forcing the right input.
Also as a tip, you don't have to limit yourself into one function.
Here's a working code below.
def getNonBlankInput(message, error_message):
x = input(message)
while len(x.strip()) == 0:
x = input(error_message)
return x
def getValidIntegerInput(message, error_message):
msg = message
while(True):
try:
x = int(input(msg))
break
except ValueError:
msg = error_message
return x
def orderFunction(): # The function which allows the customer to choose delivery or pickup
global deliveryPickup
global customerName
global customerAddress
global customerPhnum
deliveryPickup = input("Please input delivery or pickup: d for delivery p for pickup")
if deliveryPickup == "d":
customerName = getNonBlankInput("Please input your name: ", "Please input a valid name: ")
customerAddress = getNonBlankInput("Please input your address: ", "Please input a valid address: ")
customerPhnum = getValidIntegerInput("Please input your phone number: ", "Please input a valid phone number: ")
print("There will also be a $3 delivery surcharge")
elif deliveryPickup == "p":
customerName = getNonBlankInput("Please input your name: ", "Please input a valid name: ")
else:
print("Please ensure that you have chosen d for Delivery or p for Pickup")
orderFunction()
orderFunction()
Try using a regular expression that checks if any character between "A-Z" has been inserted, if not, give an error
The while loops are a decent solution, you just need to add more checks to your if statements.
First, you don't need a try statement on the top two loops. Don't use a try statement unless you're expecting an error, which you need to handle with an except statement, like you do in the bottom while loop.
Then you just need to add more conditions to your top two loops, I don't know exactly what you want to prevent, but you could try checking the length of the input, also see this answer for an interesting method:
https://stackoverflow.com/a/2405300/8201979
Instead of using input right away you can make a function similar to this one that will only allow valid inputs.
You can use this valid_input function instead of input.
def valid_input(text):
not_valid = True
res = ''
while not_valid:
res = input(text)
if res.split(): # if text is empty or only spaces, this creates an empty list evaluated at False
not_valid = False
return res
here the check is pretty simple: every text made out of nothing or spaces won't be allowed and we will keep asking for the same input until a valid information is given.
I made this code simple just so you get a general idea. But you can change the validation test to your liking and maybe also output a warning saying why the input wasn't allowed so the person knows what to do. You can do more advanced validation with regex, and maybe you need a minimum text length etc...
You have indent error because you have a try statement without the corresponding except.
You need both to make it work (as you did in the Phone number section).
Here is a link to the try/except: docs
Also, you can check if a string is empty as detailed in this answer.
So for example you want to write:
try:
customerName = input("Please input your name")
if not customerName:
print("Please input a valid name")
else:
break
except ValueError:
print("Please input a valid name")
Although the above seems a bit redundant, so you might want to raise an exception if the customer name is empty, catch the exception in the except block, print the warning and return error (or something else).
try:
customerName = input("Please input your name")
if not customerName:
raise ValueError
except ValueError:
print("Please input a valid name")
else:
break
Try adding another while true for pick and delivery option so that it can prevent taking other inputs
you don't need any of those try/excepts (which are broken anyway).
Its difficult to figure out what you're trying to do, are you trying to raise an exception if an empty string is passed, or request another input from the user? You seem to be half implementing both at the moment.
If its the latter, something like this would work.
def func(fieldname):
while True:
val = input("Please input your {}".format(fieldname))
if val.strip() != "":
break
else:
print("Please input a valid {}".format(fieldname))
return val
delivery_pickup = input("Please input delivery or pickup: d for delivery p for pickup")
if delivery_pickup == "d":
customer_name = func("name")
address = func("address")
phone_number = func("phone number")
What you are looking for is the str.strip method that remove trailing whitespace in strings.
Also I think try is not particularly suited for your needs here.
customerName = input("Please input your name")
while not customerName.strip():
customerName = input("Please input a valid name")
for the phone number I would not convert to integer because if the phone number starts with zeros, they will not be stored.
I want my code below to ask users to add contacts which i will save in a dictionary.
When user responds N to whether they want to add new contact, the loop is supposed to terminate. When Y, the loop must continue and when they enter something which is neither N nor Y, the question must keep repeating till they enter Y or N.
My code below does not return to beginning of function when i type yes
contactbook = {}
def addcontact():
name = input("Enter the name of your new contact")
number = int(input("Enter your phone contact"))
contactbook[name] = number
print("Contact book successfully updated with : ", contactbook.items())
while True:
qu = 'X'
while qu not in 'YN':
qu = input("Do you want to add a new contact? Y/N").upper()
elif qu == 'N':
break
After I reply Y to the question, I do not get the program to repeat
You can achieve that logic more cleanly by sth. like:
def addcontact():
while True: # no variable like keepadding needed
name = ...
# ...
qu = 'X'
while qu not in 'YN':
qu = input("Do you want to add a new contact? Y/N").upper()
if qu == 'N':
break
# no need to specify the 'Y' case, the outer loop just continues
This is because you are assigning to a variable named keepadding. The loop tests the value of a variable named keepreading. Because these variables are different the test will always be True and the loop will continue even if you enter N.
Update your code to initialise the variable at the top of the function and test the correct variable:
def addcontact():
keepadding = True
while keepadding:
....
Updated following OP code change:
Move the while loop to the top of the function so that the input() and contact book updates occur within the loop. Change elif to if. Here is a working version:
contactbook = {}
def addcontact():
while True:
name = input("Enter the name of your new contact")
number = int(input("Enter your phone contact"))
contactbook[name] = number
print("Contact book successfully updated with : ", contactbook.items())
qu = 'X'
while qu not in 'YN':
qu = input("Do you want to add a new contact? Y/N: ").upper()
if qu == 'N':
break
Try this:
contactbook = {}
def addcontact():
keepadding = True
while keepadding:
name = input("Enter the name of your new contact: ")
number = int(input("Enter your phone contact: "))
contactbook[name] = number
print("Contact book successfully updated with {}, {}".format(name, number))
while True:
qu = input("Do you want to add a new contact? Y/N ").upper()
if qu in 'YN':
break
print("That's not a valid input. Try again.")
keepadding = qu.upper() == 'Y'
addcontact()
This question already has answers here:
Asking the user for input until they give a valid response
(22 answers)
Closed 8 years ago.
I'm making a pizza operator program for school. what is basically does is it asks for the customers name, asks if you want pickup or delivery etc. The problems I have encountered is that when I don't type anything into the input it will give the error to make you input it but then will automatically stop the program. I would like it to repeat itself. and also I have a bug in get_user_info when I click 1, 2 or 3 it does nothing but go in a infinite loop which I cannot seem to solve. I hope you guys could help me thank you very much in advance.
Regards,
Johnathon
My code
premium_pizzas = ["Supreme Cheese", "The Legendary pizza", "Pentakill supreme", "Teeto shroomo supreme", "The volcanic rengar", "Cheese and Ham" , "Vegetriano" ]
gourmet_pizzas = ["Flame Gorrila", "Snazzy chicken", "Intergalactic BBQ", "BBQ Chicken"]
#premium_pizzas = 8.50
#gourmet_pizzas = 5.00
customer_name = ""
def get_customer_name():
customer_name =input("what is your name?\n\t")
if customer_name is "":
print("Error please enter a name!\n\t")
#else: get_user_info()
def get_delivery_details():
get_address = input("Please enter a delivery address\n\t:")
if get_address == "":
print("error you must enter a address")
get_phone_number = str(input("please enter your phone number"))
if get_phone_number is "":
print("Input must be an integer(numbers only)")
if get_phone_number is "abcdefghijklmnopqrstuvwxyz":
print("Input must be an integer(numbers only)")
else:
get_pizza_list()
def get_pizza_list():
for i in range (0,6):
None
def get_user_info():
while not get_user_info == "0":
user_input=str(input("Press 1 for delivery press\nPress 2 for pickup\nPress 3 to exit\n\t:"))
if get_user_info == "1":
get_delivery_details()
elif get_user_info == "2":
get_pizza_list()
elif get_user_info == "3":
exit
#get_user_info()
get_customer_name
#get_delivery_details()
#get_pizza_list()
You want to loop as long as the customer name is empty:
customer_name = ""
def get_customer_name():
while (customer_name == ''):
customer_name = raw_input("what is your name?\n\t")
if customer_name is "":
print("Error please enter a name!\n\t")
In addition, I would re-think the use of global variables. Programs using globals do not scale well.
def get_customer_name():
result = ''
while (result is ''):
result = raw_input("what is your name?\n\t")
if (result is ''):
print("Error please enter a name!\n\t")
return(result)
and later in the program:
customer_name = get_customer_name()
The first problem:
I would change
customer_name =input("what is your name?\n\t")
if customer_name is "":
print("Error please enter a name!\n\t")
with
customer_name=""
while customer_name == "":
customer_name =input("what is your name?\n\t")
print("Error please enter a name!\n\t")
And the other problem... quick suggestion: are you sure you wanna read user_input and use get_user_info as a variable? Just use user_input, not the name of the function :) ^^
Editing so not to pollute the edit place:
while not user_input == "3":
user_input=str(input("Press 1 for delivery press\nPress 2 for pickup\nPress 3 to exit\n\t:"))
if user_input == "1":
get_delivery_details()
else user_input == "2":
get_pizza_list()
Basically you cycle until user_input is different from 3, the (main) problem with your solution was that you were using a bogus variable (get_user_info) to perform the check to let the cycle end, BUT you were setting a different one (user_input) ;)
1. Use raw_input()
2. Work with objects/classes. It'll make your program more readable/debugable/organized.
3. Some of your if statements could be rewritten.
4. Make global variables uppercase for readability. (actually not sure if this in PEP-8 but I always do it)
Example
Here is something I made. It is dirty but it works.
PREMIUM_PIZZAS = ["Supreme Cheese", "The Legendary pizza", "Pentakill supreme", "Teeto shroomo supreme", "The volcanic rengar", "Cheese and Ham" , "Vegetriano" ]
GOURMET_PIZZAS = ["Flame Gorrila", "Snazzy chicken", "Intergalactic BBQ", "BBQ Chicken"]
class Customer():
def __init__(self):
self.name = ''
self.address = ''
self.phone = ''
self.pickup = False
self.pizza = ''
class Order():
def __init__(self):
self._customer = Customer()
def get_order(self):
if not self.get_customer_name():
return None
if not self.get_user_info():
return None
return self._customer
def get_customer_name(self):
name = raw_input("what is your name?\n\t")
if not name:
print("Please enter a name!\n\t")
else:
self._customer.name = name
return True
def get_delivery_details(self):
address = raw_input("Please enter a delivery address\n\t:")
if not address:
print("You must enter a address")
return None
self._customer.address = address
phone_number = raw_input("Please enter your phone number\n\t")
try:
self._customer.phone = int(phone_number)
except:
print("Input must be an integer(numbers only)")
return None
pizza_choice = self.get_pizza_list()
if not pizza_choice:
return None
return True
def get_pizza_list(self):
# if anything went wrong, return None
# get a listing of the pizzas here, etc
choice = PREMIUM_PIZZAS[1]
if choice:
self._customer.pizza = choice
return True
def get_user_info(self):
user_choice = raw_input("Press 1 for delivery press\nPress 2 for pickup\nPress 3 to exit\n\t:")
if user_choice == "1":
if self.get_delivery_details():
return True
elif user_choice == "2":
self._customer.pickup = True
if self.get_pizza_list():
return True
while True:
print '--\nWelcome, please order a pizza!'
order = Order()
info = order.get_order()
print '--'
if info:
for attr in [a for a in dir(info) if not a.startswith('__')]:
print '%s: %s' % (attr ,getattr(info, attr))
Output
dsc:~/bla$ python test.py
--
Welcome, please order a pizza!
what is your name?
Sander Ferdinand
Press 1 for delivery press
Press 2 for pickup
Press 3 to exit
:1
Please enter a delivery address
:The Netherlands
Please enter your phone number
8349644343
--
address: The Netherlands
name: Sander Ferdinand
phone: 8349644343
pickup: False
pizza: The Legendary pizza
--
Welcome, please order a pizza!
what is your name?
You might want to use my snippet as an example for making a class that contains all the pizzas and their individual prizes and implement that in!