Creating new instances of a class from user input - python

I am trying to make a weekly meal prep program in Python. Part of that program is having a database of recipes that the user has entered. I thought the best way to make this would be to make a class Recipe where it stores the title, ingredients (as a dictionary with the key being the ingredient and the amount being value) and then the instructions. However I can't find a way to make a new variable each time I try to input a new recipe.
This is my class code
class Recipe:
def __init__(self):
ingredients = {}
while True:
ingredient = input('Type in an ingredient. Type finish when you have added in all the ingredients. ')
if ingredient == 'finish':
break
amount = input("How much of this ingredient? ")
ingredients[ingredient]=amount
self.ingredients = ingredients
self.title = input('What is the name of the recipe? ')
self.instructions = input('Type out your recipe instructions; ')
meal1 = Recipe()
print(meal1.title)
print(meal1.ingredients)
print(meal1.instructions)
Basically this works for creating one recipe. But instead of the ''' meal1 = Recipe()''' I want to create a new recipe each time the user selects the option in the main menu to 'add a recipe' how can I accomplish this without making lots of pre-named variables.

I think the better approach is to separate between user input (menu) and the recipe class
class Recipe:
def __init__(self):
ingredients = {}
while True:
ingredient = input('Type in an ingredient. Type finish when you have added in all the ingredients. ')
if ingredient == 'finish':
break
amount = input("How much of this ingredient? ")
ingredients[ingredient]=amount
self.ingredients = ingredients
self.title = input('What is the name of the recipe? ')
self.instructions = input('Type out your recipe instructions; ')
class Menu:
def __init__(self):
self.recipes = []
while True:
print("=" * 20)
print('1. Add a recipe')
print('2. Print the recipes')
print('3. Quit')
print("=" * 20)
choice = input('What would you like to do? ')
if choice == '1':
self.add_recipe()
elif choice == '2':
self.print_recipes()
elif choice == '3':
break
else:
print('That is not a valid choice. Please try again.')
def print_recipes(self):
for recipe in self.recipes:
print(recipe.title)
print(recipe.ingredients)
print(recipe.instructions)
def add_recipe(self):
recipe = Recipe()
self.recipes.append(recipe)
Menu()
The recipe is saved in variable self.recipes. With this way, you can save as many recipes as you want.

if I understand your question properly, you want to create a fresh, brand new object every time that a user creates a recipe after inserting the instruction Type out your recipe instructions, then you can delete your object using __del__ function in your class.
class Recipe:
def __init__(self):
ingredients = {}
while True:
ingredient = input('Type in an ingredient. Type finish when you have added in all the ingredients. ')
if ingredient == 'finish':
break
amount = input("How much of this ingredient? ")
ingredients[ingredient]=amount
self.ingredients = ingredients
self.title = input('What is the name of the recipe? ')
self.instructions = input('Type out your recipe instructions; ')
def __del__(self):
print("I have been destroyed.")
and to create a new object every time:
for i in range(5):
meal1 = Recipe()
print(meal1.title)
print(meal1.ingredients)
print(meal1.instructions)
del meal1
#print(meal1) # runs into NameError: name 'meal1' is not defined
note that how __del__ behaves, it may not be called every time if the reference to the object is not counted to zero. you may see this and this.

Related

What is the error in the following program with the help of split() function?

This program is based on separating the items given by the user in sentence form and add it to a list using split() method.
total_list = []
billed_list = []
class Naveen:
question = input('what would you like to buy : ')
def shopping_cart(self,items):
items = question.split()
for item in items:
print(item)
def billed_items(self):
for item in items:
ask = input('do u really want '+ item+' ')
if ask == 'yes':
billed_list.append(item)
if ask == 'no':
pass
print(billed_list)
items = []
spacex = Naveen()
spacex.shopping_cart(items)
Without any indication of what your program should do, it's not obvious that there are any bugs. But if we assume that your program is a very basic shopping cart, it has the following problems;
The I/O should probably be handled outside the class;
The question should not be a class global;
The handling of inputs other than "yes" or "no" should be defined -- either regard everything which isn't "yes" as "no" (this is what your code currently does, but by the looks of it, by mistake), or loop until you have received either "yes" or "no" response.
The items handled in the shopping cart should be encapsulated into the instance, not global variables.
Probably try to give the class a descriptive name, rather than a random one.
So, perhaps something like this;
class ShoppingCart:
def __init__(self):
self.items = []
def shopping_cart(self, request):
self.items = request.split()
def billed_items(self):
billed = []
for item in self.items:
ask = input('Do you really want '+ item+'? ')
if ask == 'yes':
billed.append(item)
return billed
spacex = ShoppingCart()
spacex.shopping_cart(input("What would you like to buy? "))
to_pay = spacex.billed_list()
split() out of the box splits on whitespace, so you would input items in the form
carrot carrot turnip pepper
to produce the items list ['carrot', 'carrot', 'turnip', 'pepper']
Add self in front of question and you need to use seperator inside split() function.
Please check this solution code:
total_list = []
billed_list = []
class Naveen:
question = input('what would you like to buy : ')
def shopping_cart(self,items):
for item in items:
total_list.append(item)
print("Total List:", total_list)
def billed_items(self, items):
for item in items:
ask = input('do u really want '+ item+': ')
if ask == 'yes':
billed_list.append(item)
if ask == 'no':
pass
print("Billed List:", billed_list)
items = []
spacex = Naveen()
items = spacex.question.split(',')
spacex.shopping_cart(items)
spacex.billed_items(items)
Sample Input & Output:
what would you like to buy : Apple,Malta
Total List: ['Apple', 'Malta']
do u really want Apple: yes
do u really want Malta: no
Billed List: ['Apple']

User input not saving into inventory list

Basically I am making an app to better assist me at managing my ebay store. I am still very new to programming and OOP. After watching some tutorials I pieced together the following code. Everything so far works pretty well. What I am currently stuck on is when the user inputs an item for inventory, it is not saving it. And, when the user wants to view the inventory the item they added wont populate. Any input or suggestions would be much apprenticed.
def Inventory():
All_Inventory = {}
class Ebay_Inventory:
def __init__(self, manufacturer, object_type, price):
self.manufacturer = manufacturer
self.object_type = object_type
self.price = price
def add_item(self):
manufacturer = input("Enter Manufacturer: ")
object_type = input("Enter what the item is: ")
price = input("Enter price: ")
item_info = Ebay_Inventory(manufacturer, object_type, price)
All_Inventory = item_info
print("Item added successfully")
def delete_item(self):
delete = input("What is the item you want to delete?: ")
if delete in All_Inventory.keys():
del[delete]
print("The item entered has been deleted.")
else:
print("Item not found")
def sale_status(self):
update = input("What is the item you want to update?:")
if update in All_Inventory.keys():
pass
else:
print("Item not found")
user=True
while user:
print("\n1. Add to item inventory")
print("2. Remove item from inventory")
print("3. Update sale status")
print("4. View inventory")
print("5. Exit program")
user_wants=input("What would you like to do today?")
if user_wants=="1":
Ebay_Inventory.add_item(input)
elif user_wants=="2":
Ebay_Inventory.delete_item(input)
elif user_wants=="3":
Ebay_Inventory.sale_status(input)
elif user_wants=="4":
print(All_Inventory)
elif user_wants=="5":
print("\n Thank you for using item inventory.")
break
elif user_wants!="":
print("\n Input not understood. Please try again.")
You need to read about Scope, OOP and dicts:
You are not adding to your Inventory.All_Inventory - you create a new local with All_Inventory = item_info
https://docs.python.org/3/tutorial/classes.html#python-scopes-and-namespaces
Short description of the scoping rules?
You mix up static class attributes and instance attributes, read:
https://docs.python.org/3/tutorial/classes.html#class-objects.
What is the difference between #staticmethod and #classmethod?
You are deleting / accessing your dictionary wrongly - see :
https://docs.python.org/3/tutorial/datastructures.html#dictionaries
Delete an element from a dictionary
Fixed:
class Ebay_Inventory:
Inventory = {} # class property
#staticmethod
def print_inventory():
for k in Ebay_Inventory.Inventory:
for i in Ebay_Inventory.Inventory[k]:
print(k,i)
class Ebay_Item:
def __init__(self, key, manufacturer, object_type, price):
self.manufacturer = manufacturer
self.object_type = object_type
self.price = price
self.key = key
def __str__(self):
return f"{self.manufacturer} {self.object_type} {self.price}"
def __repr__(self):
return str(self)
#staticmethod
def add_item(key=None, man=None, obj=None, pri=None):
# use values if given, else ask - this is for demo purposes only
key = key or input("Enter key: ")
manufacturer = man or input("Enter Manufacturer: ")
object_type = obj or input("Enter what the item is: ")
price = pri or input("Enter price: ")
# create new item
item_info = Ebay_Inventory.Ebay_Item(key, manufacturer, object_type, price)
# add to class member, create key if need be
Ebay_Inventory.Inventory.setdefault(item_info.key,[]).append(item_info)
def delete_item(key=None):
delete = key or input("What is the item you want to delete?: ")
if delete in Ebay_Inventory.Inventory:
del Ebay_Inventory.Inventory[delete]
print("The item entered has been deleted.")
else:
print("Item not found")
def __str__(self):
return Ebay_Inventory.print_inventory()
# add 2 items and print
Ebay_Inventory.add_item(1,"Me","Me",1000)
Ebay_Inventory.add_item(2,"You","You",1000)
Ebay_Inventory.print_inventory()
# remove non existent and existent item and print
Ebay_Inventory.delete_item(3)
Ebay_Inventory.delete_item(2)
Ebay_Inventory.print_inventory()
Output:
1 Me Me 1000
2 You You 1000
Item not found
The item entered has been deleted.
1 Me Me 1000
Sorry to rework your code pretty extensively, but I think this is more like what you are going for:
class EbayInventory:
def __init__(self):
self.all_inventory = []
def print_items(self):
print('Current item list by index:')
for i in range(0, len(self.all_inventory)):
print("{} -> {}".format(i+1, self.all_inventory[i]))
def add_item(self):
manufacturer = input("Enter Manufacturer: ")
object_type = input("Enter what the item is: ")
price = input("Enter price: ")
item = {'manufacturer': manufacturer, 'type': object_type, 'price': price}
self.all_inventory.append(item)
print("Item added successfully")
def delete_item(self):
self.print_items()
delete = int(input("Item id you want to delete: "))
try:
del self.all_inventory[delete - 1]
print("The item entered has been deleted.")
except Exception as e:
print("An error occurred deleting that item, details below")
print(e)
def sale_status(self):
self.print_items()
update_index = int(input("Item id you want to update: "))
if update_index > len(self.all_inventory) or update_index <= 0:
print("You're trying to change an item that doesn't exist!!")
return
print("OK. Let's get that item up to date!")
manufacturer = input("Enter Manufacturer: ")
object_type = input("Enter what the item is: ")
price = input("Enter price: ")
item = {'manufacturer': manufacturer, 'type': object_type, 'price': price}
self.all_inventory[update_index - 1] = item
print("OK. We got that update taken care of")
if __name__ == "__main__":
my_app = EbayInventory()
while True:
print("\n1. Add to item inventory")
print("2. Remove item from inventory")
print("3. Update sale status")
print("4. View inventory")
print("5. Exit program")
user_wants = input("Please enter the number corresponding to how you would like help: ")
if user_wants == "1":
my_app.add_item()
elif user_wants == "2":
my_app.delete_item()
elif user_wants == "3":
my_app.sale_status()
elif user_wants == "4":
my_app.print_items()
elif user_wants == "5":
print("Thank you for using item inventory.")
break
else:
print("Input not understood. Please try again.")
You had a variable user that did nothing. You can simply enter an infinite loop with while True:. If you wanted to loop the way you did, then instead of a break you could have put a user = False to break out of the loop. This is sometimes a nifty trick, but doesn't make sense here I think. It seemed to me the inventory was really the only thing that would benefit by being stored in your class, and the methods could then access it to adjust it via a self.all_inventory. I moved your code to ask for item inputs to the add_item() and sale_status() methods, so now the main block of code looks a lot cleaner. I also wrapped it in if __name__ == "__main__": so that you can import this class to another project without running the entire program! I threw in some basic error checking with try: and except: clauses also. I think you were misunderstanding the difference between a Class and an Instance. So in my code the Class is EbayInventory, but the Instance is my_app. You create instances of your class just like I did with my_app = EbayInventory() and then the self now refers to my_app. In this manner I can call my_app.add_item(). You can have several instances of objects though, and they each have their own space in your computers memory. So you could have said:
app1 = EbayInventory()
app2 = EbayInventory()
app1.add_item()
And only the app1 will have any items, whereas app2 is still an empty list, but still has the methods to build an inventory via app2.add_item(). To answer your main question though, you never call your function Inventory() and therefore it doesn't exist to hold your information. When you call item_info = Ebay_Inventory(manufacturer, object_type, price) in fact you are making an Instance of a class, which is really nonsensical to do here because that means on the next line you could say item_info.add_item() and this would make another instance, yet you are not saving this information anywhere so you can never retrieve it!

Struggling with Python syntax when trying to check if a string from an input is in a variable

I’m finding the Python syntax very confusing, mainly concerning variables. I’m trying to learn it using the Microsoft EDX course but I’m struggling when trying to check if a string from an input is in the variable.
Example 1: Check if a flavor is on the list
# menu variable with 3 flavors
def menu (flavor1, flavor2, flavor3):
flavors = 'cocoa, chocolate, vanilla'
return menu
# request data from the user flavorName = input('What flavor do your want? ')
data = input("What flavor do you want? ")
#print the result
print ("It is", data in menu, "that the flavor is available")
Example 2: Print a message indicating name and price of a car
def car (name, price):
name = input(“Name of the car: “)
price = input (“Price of the car: “)
return (name, price)
print (name, “’s price is”, price)
Also, I would like to know what would be the disadvantage of doing something like this for the example 2:
name = input("name of the car: ")
price = input ("price of the car: ")
print (name,"is", price,"dollars")
Could someone please clarify this to me? Thank you very much!
i didnt understand what your trying to do in first example.
But i can partially understand what your trying to do in second example,
def car ():
name = input("Name of the car: ")
price = input ("Price of the car: ")
return name, price
name,price = car()
print ("{}\'s price is {}".format(name,price))
the above code is the one of the way to solve your problem,
python can return multiple variable
use format function in print statement for clean display.
You dont need function parameters for car. since your taking input from in car function and returning it to the main.
Hope it helps you understand.
Example 1
# menu variable with 3 flavors
def menu():
flavors = 'cocoa, chocolate, vanilla'
return flavors #return flavors instead of menu
# request data from the user flavorName = input('What flavor do your want? ')
data = input("What flavor do you want? ")
# print the result
print ("It is", data in menu(), "that the flavor is available") #menu is a function so invoke with menu () instead of menu
Example 2:
def car(): #no input required since you are getting the input below
name = input('Name of the car: ')
price = input('Price of the car: ')
return (name, price)
name, price = car() #call the function to return the values for name and price
print (name, "’s price is", price)
The below approach works and is faster as compared to calling the function although adding small stuff to form functions allows the program to be modularized, making it easier to debug and reprogram later as well as better understanding for a new programmer working on the piece of code.
name = input("name of the car: ")
price = input("price of the car: ")
print (name, "is", price, "dollars")
Just found how to print the result in the way the exercise required. I had difficulty explaining, but here it is an example showing:
def car(name,price):
name_entry = input("Name car: ")
price_entry = input("Price car: ")
return (name_entry,price_entry)
This is the way to print the input previously obtained
print (car(name_entry,price_entry))
Thank you very much for all the explanations!

Tying values to keys in a dictionary and then printing

This is a smaller portion of the main code I have been writing. Depending on user selection they can add player informationa and then print the information from the dictionary player roster. I want to store the information and then print in this format but I havent been able to figure out how to do this.
Name ****
Phone Number ****
Jersey Number ****
Im new to dictionaries but I have spent hours reading and searching over the past couple of days about dictionaries and have tried several different ways to do this but failed. I have gotten the closest the way I have it setup now but it still doesnt work right. I feel like I am storing the information incorrectly into the dictionary for starters, any help would be greatly appreciated.
player_roster = {}
def display_roster(self): #Print Roster
if len(player_roster) != 0:
for x in player_roster.keys():
print('Name:', x, 'Phone Number:', player_roster[x])
else: #Print No One on Roster
len(player_roster) == []
print('No names have been entered:')
def add_player(self,): #Enter Members Name
name = input('Enter New Players Name:')
phone_number = input('Enter Players Phone Number:')
jersey_number = int(input('Enter Players Jersey Number'))
player_roster[name] = phone_number, 'Jersey Number', jersey_number
#If I input Toby as Name 444-444 as Phone Number and 3 as Jersey number it outputs like this
Name: Toby Phone Number: ('444-4444', 'Jersey Number', 3)
# I would like it to output like
Name: Toby
Phone Number: 444-4444
Jersey Number: 3
There are some things i would change in your code but to keep this close to what you asked for take a look at this:
def display_roster():
if len(player_roster) != 0:
for x in player_roster.keys():
print('Name:', x)
print('Phone Number:', player_roster[x][0])
print('Jersey Number:', player_roster[x][1])
else:
print('Roster is empty.')
return
player_roster = {}
def add_player():
name = input('Enter New Players Name:\t')
phone_number = input('Enter Players Phone Number:\t')
jersey_number = int(input('Enter Players Jersey Number:\t'))
player_roster[name] = [phone_number, jersey_number]
return
add_player()
display_roster()
# PRINTS:
#Name: Toby
#Phone Number: 444-4444
#Jersey Number: 3
Printing in multiple lines gives you the result you want. As stated in the comments this can also be done with a single print() statement but i do not think compact code makes much difference to you yet.
Further, this len(self.player_roster) == [] line does not make sense. This is as good as simply writing True in a line. The "emptiness" of the team is checked by the else:.
Finally, i would slightly change the way players are stored in the "Roster" dictionary and have it like this: {"Toby": ['444-4444', 3], ...}
I would propose that you replace the print statement to this:
print(" Name: %s \n Phone Number: %s \n Jersey Number: %d") % player_roster[x]
You're pretty much there. The below modification would allow you to print as you need (and is slightly more readable):
class PlayerDictionary():
def __init__(self):
pass
player_roster = {}
def display_roster(self): #Print Roster
if len(self.player_roster) != 0:
for key, value in self.player_roster.iteritems():
print(str(key) + ": " + str(value))
else: #Print No One on Roster
len(self.player_roster) == []
print('No names have been entered:')
def add_player(self,):
self.player_roster['Name'] = input('Enter New Players Name:')
self.player_roster['Phone Number'] = input('Enter Players Phone Number:')
self.player_roster['Jersey Number'] = int(input('Enter Players Jersey Number'))
if __name__ == "__main__":
player = PlayerDictionary()
player.add_player()
player.display_roster()
A slightly more maintainable solution would be to create a class for Player. Set the properties on the object and overload the str function e.g.
class Player(object):
def __init__(self):
self.__name = ""
self.__phone_number = ""
self.__jersey_number = ""
#property
def name(self):
return self.__name
#property
def phone_number(self):
return self.__phone_number
#property
def jersey_number(self):
return self.__jersey_number
#name.setter
def name(self, val):
self.__name = val
#phone_number.setter
def phone_number(self, val):
self.__phone_number = val
#jersey_number.setter
def jersey_number(self, val):
self.__jersey_number = val
def __str__(self):
return ("Name: %s\nPhone Number: %s\nJersey Number: %s" % (str(self.__name), str(self.__phone_number), str(self.__jersey_number)))
if __name__ == "__main__":
player = Player()
player.name = input('Enter New Players Name:')
player.phone_number = input('Enter Players Phone Number:')
player.jersey_number = int(input('Enter Players Jersey Number'))
print(player)

Recipe Finder, Python 3. Definition error when saving a recipe

Below is the code that I have the issue with. When it comes to saving a new recipe, it comes up with an error saying that 'dish' is not defined. 'dish' is the variable that holds the recipe name. To get to this stage, the name must have already been entered, and so I fail to see why the error should occur. I would be very grateful to here of any comments and tips, as i have hit the metaphorical 'brick wall.'
import sys
recipes = []
ingredients = []
quantities = []
menu = "What would you like to do? \n 1) Make a recipe \n 2) Load a recipe \n 3) Exit \n\
"
def save_recipe(recipe, file_name):
file = open(file_name, "w")
file.write(recipe)
file.close()
def decision_functions():
interface_choice = input(menu)
if (interface_choice == "1" or "Make a recipe"):
dish = input("What do you wish to make?: ")
ingredients_loop()
elif (interface_choice == "2" or "Load a recipe"):
decision = input("What recipe do you wish to load?: ")
decision += ".txt"
file = open(decision, "r")
recipe = (file.read())
serves = int(input("How many do you wish to serve?: "))
recipe = list(recipe)
elif (interface_choice == "3" or "Exit"):
print("Goodbye!")
sys.exit
else:
print("I don't understand. . . Please select one of the above numbered options. \n\
")
decision_functions
def ingredients_loop():
ingredient = input("Name an ingredient in the recipe. Type END when done: ")
if (ingredient == "end"):
def confirm_decision():
print(ingredients)
print(quantities)
confirmation = input("Is this all?: ")
if (confirmation == "yes"):
recipe = [ingredients, "\n\
" , quantities]
file_name = dish.replace(' ', '') + ".txt"
writerecipe(str(recipe), file_name)
print("Your recipe has been saved")
decision_functions()
elif (confirmation == "no"):
print("Preparing to allow more ingredients. . .")
ingredients_loop()
else:
print("I do not understand . . .")
confirm_decision()
confirm_decision()
else:
ingredient += ":"
ingredients.append (ingredient)
amount = int(input("How much of this ingredeint is required to serve one?: "))
units = (input("What unit is this measurement in?: "))
amts = amount, units
quantities.append (amts)
ingredients_loop()
decision_functions()
You are using dish inside the ingredients_loop Which is not accessible since you have declared inside the decision_functions
What you can do is either make dish as global or pass the dish to ingredients_loop
recipes = []
ingredients = []
quantities = []
dish =""
menu = "What would you like to do? \n 1) Make a recipe \n 2) Load a recipe \n 3) Exit \n\
"
specify dish as global

Categories