This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 3 years ago.
I'm running this code and when i add an item to the inventory,the item appears in all the Inventory Classes, Where am I going wrong here?
Once i run Browse(),add new inventory,add items to it,
and when i make a new inventory, items from the first inventory appear in the new one by default.
how can i fix this problem boys and girls?
inventories = {}
class Inventory: ##Class for new inventory
inventory = {}
items = {}
def __init__(self,name):
self.name = name
def add_item(self,item,price,amount):
if item in self.items:
return False
else:
self.items[item] = int(price)
self.inventory[item] = int(amount)
return True
def add_amount(self,item,amount):
self.inventory[item] += amount
def update_amount(self,item,amount):
self.inventory[item] = amount
def remove_amount(self,item,amount):
self.inventory[item] -= amount
def update_item_price(self,item,price):
self.items[item] = price
def inv_list(self): ##Print the class
print(self.name)
print("\nItem: Price: Amount:\n")
for item in self.inventory:
print(f"{item}\t\t{self.items[item]}\t\t{self.inventory[item]}")
def new_inventory(): ##MAkes a new inventory class and stores in inventories{}
global inventories
while True:
answer = input("What would you like to call your new Inventory?")
if answer in inventories:
print("Name already taken")
continue
inventories[answer] = Inventory(answer)
print("Inventory created")
update(answer)
break
def update(inv): ##Updates an excisting Inventory
global inventories
while True:
inventories[inv].inv_list()
answer = int(input("1.Add item to inventory\n2.Update items price\n3.Update items amount\n4.Exit"))
if answer == 1:
while True:
name = input("Name of item")
price = int(input("Price"))
amount = int(input("Amount"))
answer = inventories[inv].add_item(name,price,amount)
if answer == False:
print("Item already in inventory")
continue
break
if answer == 2:
while True:
print(inventories[inv].inv_list())
name = input("item")
price = int(input("Price"))
if name in inventories[inv].items:
inventories[inv].update_item_price(name,price)
break
print("No such item")
continue
if answer == 3:
while True:
print(inventories[inv].inv_list())
name = input("item")
amount = int(input("Amount"))
if name in inventories[inv].items:
inventories[inv].update_amount(name,amount)
break
print("No such item")
continue
if answer == 4:
break
def browse(): ##Runs the prigram Function
global inventories
while True:
print("Welcome to your inventory collection\nWhat action would you like to take?")
print("1.Add a new inventory list\n2.Update excisting inventory\n3.Exit")
answer = int(input())
if answer == 1:
new_inventory()
if answer == 2:
for x in inventories:
print(x)
while True:
answer = input("Which inv?")
if answer in inventories:
update(answer)
break
if answer == "exit":
break
continue
if answer == 3:
print("Goodbye")
break
else:
continue
browse()
inventory = {}
items = {}
is creating shared attributes for all class instances. You should initialize the attributes in the __init__ method.
class inventory:
def __init__(self, name):
self.name = name
self.inventory = {}
self.items = {}
Related
I have an inventory program that stores the ID number, item name, and the quantity in three different lists. These three lists are combined in an inventory list but, when the data is saves to a TextEdit document it stores the data in three different lists. How do I save this data in one dictionary. First ID number, item name, then qty.
Here is the full program code:
import os
class Inventory:
def __init__(self):
#AT LAUNCH GROUPS AND LOADING FUNCTION
self.ID = []
self.item = []
self.qty = []
self.load()
def remove(self, ID):
#REMOVING ITEMS FOR LISTS AND OUTPUT DOCUMENT
ix = self.ID.index(ID)
self.ID.pop(ix)
self.item.pop(ix)
self.qty.pop(ix)
self.save()
def add(self, ID, name, qty):
#ADDING ITEMS FOR LISTS AND OUTPUT DOCUMENT
self.ID.append(ID)
self.item.append(name)
self.qty.append(qty)
self.save()
def update(self, ID, update):
#UPDATING ITEMS FOR LISTS AND OUTPUT DOCUMENT
if update >= 0:
self.qty[self.ID.index(ID)] += update
elif update <= -1:
self.qty[self.ID.index(ID)] += update
self.save()
def search(self, ID):
#SEARCHING ITEMS FOR LISTS
pos = self.ID.index(ID) if ID in self.ID else -1
if pos >= 0:
return self.ID[pos], self.item[pos], self.qty[pos]
else:
return None
def __str__(self):
#FORMATTING
out = ""
zipo = list(zip(self.ID, self.item, self.qty))
for foobar in zipo:
out += f"ID Number : {foobar[0]} \nItem Name : {foobar[1]}\nQuantity : {foobar[2]}\n"
out += "----------\n"
return out
def save(self):
#WHERE TO SAVE TO
with open('inventory.dat','w') as f:
f.write(str(self.ID) + '\n' + str(self.item) + '\n' + str(self.qty))
def load(self):
#WHERE TO PUT DATA FROM WHEN RELAUNCHING PROGRAM
from os import path
if path.exists('inventory.dat'):
with open('inventory.dat','r') as f:
lns = f.readlines()
self.ID = eval(lns[0])
self.item = eval(lns[1])
self.qty = eval(lns[2])
def menuDisplay():
#MENU FOR PROGRAM
"""Display the menu"""
print('=============================')
print('= Inventory Management Menu =')
print('=============================')
print('(1) Add New Item to Inventory')
print('(2) Remove Item from Inventory')
print('(3) Update Inventory')
print('(4) Search Item in Inventory')
print('(5) Print Inventory Report')
print('(99) Quit')
def add_one_item(inventory):
#ADDING PROMPT AND ERROR CHECKING
print('Adding Inventory')
print('================')
while True:
try:
new_ID = int(input("Enter an ID number for the item: "))
if new_ID in inventory.ID:
print("ID number is taken, please enter a different ID number")
continue
new_name = input('Enter the name of the item: ').lower()
assert new_name.isalpha(), "Only letters are allowed!"
new_qty = int(input("Enter the quantity of the item: "))
inventory.add(new_ID, new_name, new_qty)
break
except Exception as e:
print("Invalid choice! try again! " + str(e))
print()
def remove_one_item(inventory):
#REMOVING PROMPT AND ERROR CHECKING
print('Removing Inventory')
print('==================')
removing = int(input("Enter the item's ID number to remove from inventory: "))
inventory.remove(removing)
def ask_exit_or_continue():
#OPTION TO CONTINUE OR QUITE PROGRAM
return int(input('Enter 98 to continue or 99 to exit: '))
def update_inventory(inventory):
#UPDATING PROMPT AND ERROR CHECKING
print('Updating Inventory')
print('==================')
ID = int(input("Enter the item's ID number to update: "))
update = int(input("Enter the updated quantity. Enter 5 for additional or -5 for less: "))
inventory.update(ID, update)
def search_inventory(inventory):
#SEARCHING PROMPT AND ERROR CHECKING
print('Searching Inventory')
print('===================')
search = int(input("Enter the ID number of the item: "))
result = inventory.search(search)
if result is None:
print("Item not in inventory")
else:
ID, name, qty = result
print('ID Number: ', ID)
print('Item: ', name)
print('Quantity: ', qty)
print('----------')
def print_inventory(inventory):
#PRINT CURRENT LIST OF ITEMS IN INVENTORY
print('Current Inventory')
print('=================')
print(inventory)
def main():
#PROGRAM RUNNING COMMAND AND ERROR CHECKING
inventory = Inventory()
while True:
try:
menuDisplay()
CHOICE = int(input("Enter choice: "))
if CHOICE in [1, 2, 3, 4, 5]:
if CHOICE == 1:
add_one_item(inventory)
elif CHOICE == 2:
remove_one_item(inventory)
elif CHOICE == 3:
update_inventory(inventory)
elif CHOICE == 4:
search_inventory(inventory)
elif CHOICE == 5:
print_inventory(inventory)
exit_choice = ask_exit_or_continue()
if exit_choice == 99:
exit()
elif CHOICE == 99:
exit()
except Exception as e:
print("Invalid choice! try again!"+str(e))
print()
# If the user pick an invalid choice,
# the program will come to here and
# then loop back.
main()
Thank you in advance.
Don't use 3 lists, use a dictionary containing dictionaries. The keys of the main dictionary will be the IDs, and the values will be dictionaries containing the name and quantity.
You can use JSON or pickle to save and load the data.
import os
import json
class Inventory:
def __init__(self):
#AT LAUNCH GROUPS AND LOADING FUNCTION
self.items = {}
self.load()
def remove(self, ID):
#REMOVING ITEMS FOR LISTS AND OUTPUT DOCUMENT
del self.items[ID]
self.save()
def add(self, ID, name, qty):
#ADDING ITEMS FOR LISTS AND OUTPUT DOCUMENT
self.items[ID] = {"name": name, "qty": qty}
self.save()
def update(self, ID, update):
#UPDATING ITEMS FOR LISTS AND OUTPUT DOCUMENT
self.items[ID]["qty"] += update
self.save()
def search(self, ID):
#SEARCHING ITEMS FOR LISTS
item = self.items.get(ID, None)
if item:
return ID, item['name'], item['qty']
else:
return None
def __str__(self):
#FORMATTING
out = ""
for id, d in self.items.items():
out += f"ID Number : {id} \nItem Name : {d['name']}\nQuantity : {d['qty']}\n"
out += "----------\n"
return out
def save(self):
#WHERE TO SAVE TO
with open('inventory.dat','w') as f:
json.dump(self.items, f)
def load(self):
#WHERE TO PUT DATA FROM WHEN RELAUNCHING PROGRAM
try:
with open('inventory.dat','r') as f:
self.items = json.load(f)
except:
print("Can't load old inventory, starting fresh")
self.items = {}
You should avoid accessing attributes directly outside the class, as it makes it difficult to reimplement the class so
if new_ID in inventory.ID:
should be
if inventory.search(new_ID):
I have a program that totally works except I have to have it report how many item are left in inventory after the user "checkout" (option 2). I have created a function called inhand. In this function I assigned each item in inventory with the qty of 100. The following line is suppose to take the item the user selected and subtract the qty they entered. After the user chooses option 2 "checkout". It prints a "bill". I want it to print how many of each item is left in inventory. Instead it currently errors. How do I fix this?
Full Code:
#DEFINING EACH RETAIL ITEM TEMPLATE
class RetailItem:
def __init__(self,desc,unit,price):
self.description = desc
self.units = unit
self.price = price
#CREATING WHERE SELECTED ITEMS WITH RESIDE
class CashRegister:
def __init__(self):
self.shopping_list=[]
def purchase_item(self,retail):
#adding item to list
self.shopping_list.append(retail)
#CREATING PRICING / COST
def get_total(self):
total = 0
for i in self.shopping_list:
total+=(i.units*i.price)
return total
#HOW THE CHECKOUT WILL FORMAT/LOOK IN AFFECT ON OPTION 2 (CHECKOUT)
def show_items(self):
if not self.shopping_list:
return
print("{:<15}{:<25}{:<25}{:<10}".format(" "*9,"Description","Units","Price"))
print("-"*75)
for c,i in enumerate(self.shopping_list,1):
print("{:<15}{:<25}{:<25}{:<10}".format("Item #"+str(c),i.description,i.units,i.price))
print("-"*75)
def inhand():
inventory = { "Pants":100, "Shirt":100, "Dress":100, "Socks":100, "Sweater":100 }
inventory[item_type] -= qty_purchased
def main():
#ADDING TO CART
c=CashRegister()
#MENU
while 1:
try:
print("1. Purchase\n2. Checkout\n3. Clear\n4. Exit")
print()
choice = int(input("Enter your choice: "))
print()
if choice == 1:
while 1:
print()
print("Menu\n-----------------------\n1. Pants\n2. Shirt\n3. Dress\n4. Socks\n5. Sweater")
item_type = int(input("Select item: "))
print()
qty=int(input("Enter quantity: "))
#ITEMS TO CHOOSE FROM AND ADD TO CART
if item_type == 1:
c.purchase_item(RetailItem("Pants",qty,44.95))
elif item_type == 2:
c.purchase_item(RetailItem("Shirt",qty,34.95))
elif item_type == 3:
c.purchase_item(RetailItem("Dress",qty,79.95))
elif item_type == 4:
c.purchase_item(RetailItem("Socks",qty,6.95))
elif item_type == 5:
c.purchase_item(RetailItem("Sweater",qty,24.95))
else:
#ERROR MESSAGE
print("Invalid item! try again")
print()
continue
print("Item added to list")
print()
break
elif choice == 2:
if not c.shopping_list:
#ERROR MESSAGE
print("Nothing to checkout!")
print()
continue
#DISPLAYING BILL
c.show_items()
print(" "*60+"Total: ${}".format(round(c.get_total(),2)))
print()
print(inhand)
elif choice == 3:
#CLEARING
c.shopping_list=[]
elif choice == 4:
#EXIT
exit()
else:
#ERROR MESSAGE
print("Invalid choice! try again!")
print()
#ERROR MESSAGE
except Exception as e:
print("Invalid choice! try again!"+str(e))
print()
#RUN PROGRAM
if __name__ == "__main__":
main()
you must declare that inhand function scope variable first as well making the function accessible throughout the class, then assign inventory to your class variable otherwise it wont get stored globally in your class (only inside of your function) for example:
def inhand(self,item_type,qty_purchased):
self.inventory = { "Pants":100, "Shirt":100, "Dress":100, "Socks":100, "Sweater":100 }
self.inventory[item_type] -= qty_purchased
so then you can use it repetitively using for loop
self.item_type_qty[["Pants",20],["Dress",20]] #for example, this variable store user picked item
for x in self.item_type_qty:
self.inhand(x[0],x[1]) #calling inhand function repetitively
you will also need to validate if in case those inventory get valued below zero. which at this point you can figure it out on your own. good luck
Initialize the inventory in the constructor. Let the inhand function check the inventory and return True\False if the purchase can be made.
Try this code:
#CREATING WHERE SELECTED ITEMS WITH RESIDE
class CashRegister:
def __init__(self):
self.shopping_list=[]
self.inventory = { "Pants":100, "Shirt":100, "Dress":100, "Socks":100, "Sweater":100 }
def purchase_item(self,retail):
#adding item to list
if self.inhand(retail.description, retail.units):
self.shopping_list.append(retail)
#CREATING PRICING / COST
def get_total(self):
total = 0
for i in self.shopping_list:
total+=(i.units*i.price)
return total
#HOW THE CHECKOUT WILL FORMAT/LOOK IN AFFECT ON OPTION 2 (CHECKOUT)
def show_items(self):
if not self.shopping_list:
return
print("{:<15}{:<25}{:<25}{:<10}".format(" "*9,"Description","Units","Price"))
print("-"*75)
for c,i in enumerate(self.shopping_list,1):
print("{:<15}{:<25}{:<25}{:<10}".format("Item #"+str(c),i.description,i.units,i.price))
print("-"*75)
def inhand(self,item_type,qty_purchased):
if self.inventory[item_type] < qty_purchased:
print(f"Cannot purchase {qty_purchased} {item_type}. Only {self.inventory[item_type]} left in stock.")
return False
self.inventory[item_type] -= qty_purchased
return True
You can print the inventory after printing the cart:
#DISPLAYING BILL
c.show_items()
print(" "*60+"Total: ${}".format(round(c.get_total(),2)))
print()
print(">> Inventory:", c.inventory)
I have a program that has a search option that if chicken or Chicken is in inventory it will pull up the item by just typing chi (not case-sensitive). The issue is how do I make the function return all items that contain chi?
For example if I have Chickens, chicken, chickens, and Chicken in inventory I should be able to type in chi and it should print out all the information about each item.
Affected Code (not full program):
def search(self, query):
#SEARCHING DATA BASED ON CLOSEST CHARACTER MATCH - NOT CASE SENSITIVE
for id in self.items:
if str(query) == id or self.items[id]['name'].lower().startswith(str(query).lower()):
return id, self.items[id]['name'], self.items[id]['qty']
return None
How do I fix this?
Full program code for testing:
import os
import json
class Inventory:
def __init__(self):
#AT LAUNCH GROUPS AND LOADING FUNCTION
self.items = {}
self.load()
def remove(self, ID):
#REMOVING ITEMS FOR LISTS AND OUTPUT DOCUMENT
del self.items[str(ID)]
self.save()
def add(self, ID, name, qty):
#ADDING ITEMS FOR LISTS AND OUTPUT DOCUMENT
self.items[str(ID)] = {"name": name, "qty": qty}
self.save()
def update(self, ID, update):
#UPDATING ITEMS FOR LISTS AND OUTPUT DOCUMENT
self.items[str(ID)]["qty"] += update
self.save()
def search(self, query):
#SEARCHING DATA BASED ON CLOSEST CHARACTER MATCH - NOT CASE SENSITIVE
output = []
for id in self.items:
if str(query) == id or self.items[id]['name'].lower().startswith(str(query).lower()):
output.append((id, self.items[id]['name'], self.items[id]['qty']))
if output: return output
else: return None
def __str__(self):
#FORMATTING
out = ""
for id, d in self.items.items():
out += f"ID Number : {id} \nItem Name : {d['name']}\nQuantity : {d['qty']}\n"
out += "----------\n"
return out
def save(self):
#WHERE TO SAVE TO
with open('data.txt','w') as outfile:
json.dump(self.items, outfile)
def load(self):
#WHERE TO PUT DATA FROM WHEN RELAUNCHING PROGRAM
try:
with open('data.txt','r') as json_file:
self.items = json.load(json_file)
except:
print("Can't load old inventory, starting fresh")
self.items = {}
def menuDisplay():
#MENU FOR PROGRAM
"""Display the menu"""
print('=============================')
print('= Inventory Management Menu =')
print('=============================')
print('(1) Add New Item to Inventory')
print('(2) Remove Item from Inventory')
print('(3) Update Inventory')
print('(4) Search Item in Inventory')
print('(5) Print Inventory Report')
print('(99) Quit')
def add_one_item(inventory):
#ADDING PROMPT AND ERROR CHECKING
print('Adding Inventory')
print('================')
while True:
try:
new_ID = int(input("Enter an ID number for the item: "))
if inventory.search(new_ID):
print("ID number is taken, please enter a different ID number")
continue
new_name = input('Enter the name of the item: ')
new_qty = int(input("Enter the quantity of the item: "))
inventory.add(new_ID, new_name, new_qty)
break
except Exception as e:
print("Invalid choice! try again! " + str(e))
print()
def remove_one_item(inventory):
#REMOVING PROMPT AND ERROR CHECKING
print('Removing Inventory')
print('==================')
while True:
try:
removing = int(input("Enter the item's ID number to remove from inventory: "))
if inventory.search(removing):
inventory.remove(removing)
else:
print("Item not in inventory")
continue
break
except Exception as e:
print("Invalid choice! try again! " + str(e))
print()
def ask_exit_or_continue():
#OPTION TO CONTINUE OR QUITE PROGRAM
return int(input('Enter 98 to continue or 99 to exit: '))
def update_inventory(inventory):
#UPDATING PROMPT AND ERROR CHECKING
print('Updating Inventory')
print('==================')
while True:
try:
ID = int(input("Enter the item's ID number to update: "))
if inventory.search(ID):
update = int(input("Enter the updated quantity. Enter 5 for additional or -5 for less: "))
inventory.update(ID, update)
else:
print("ID number is not in the system, please enter a different ID number")
continue
break
except Exception as e:
print("Invalid choice! try again! " + str(e))
print()
def search_inventory(inventory):
#SEARCHING PROMPT AND ERROR CHECKING
print('Searching Inventory')
print('===================')
while True:
try:
search = input("Enter the name of the item: ")
result = inventory.search(search)
if result is None:
print("Item not in inventory")
continue
else:
for found in result:
ID, name, qty = found
print('ID Number: ', ID)
print('Item: ', name)
print('Quantity: ', qty)
print('----------')
break
except Exception as e:
print("Invalid choice! try again! " + str(e))
print()
def print_inventory(inventory):
#PRINT CURRENT LIST OF ITEMS IN INVENTORY
print('Current Inventory')
print('=================')
print(inventory)
def main():
#PROGRAM RUNNING COMMAND AND ERROR CHECKING
inventory = Inventory()
while True:
try:
menuDisplay()
CHOICE = int(input("Enter choice: "))
if CHOICE in [1, 2, 3, 4, 5]:
if CHOICE == 1:
add_one_item(inventory)
elif CHOICE == 2:
remove_one_item(inventory)
elif CHOICE == 3:
update_inventory(inventory)
elif CHOICE == 4:
search_inventory(inventory)
elif CHOICE == 5:
print_inventory(inventory)
exit_choice = ask_exit_or_continue()
if exit_choice == 99:
exit()
elif CHOICE == 99:
exit()
except Exception as e:
print("Invalid choice! try again!"+str(e))
print()
# If the user pick an invalid choice,
# the program will come to here and
# then loop back.
main()
def search(self, query):
#SEARCHING DATA BASED ON CLOSEST CHARACTER MATCH - NOT CASE SENSITIVE
output = []
for id in self.items:
if str(query) == id or self.items[id]['name'].lower().startswith(str(query).lower()):
output.append((id, self.items[id]['name'], self.items[id]['qty']))
if output:
return output
else:
return None
If you find this unexplainable, maybe I got the question wrong. You should try and explain better more.
The code returns the first match. This search returns all matches.
def search(self, query):
""" Search items for all matching id's in query.
"""
output = [id for id in self.items if str(query).upper() in id.upper()]
return output if output != [] else None
As a stand-alone demo I constructed a Class having a database of 3 items and a search method.
For the search method I use 'if str(query).upper() in id.upper()' in a list comprehension.
class Db:
def __init__(self):
self.items = {
'Picture1': {'name': 'name1', 'qty': 1},
'Picture2': {'name': 'name2', 'qty': 2},
'Picture3': {'name': 'name3', 'qty': 3}}
def search(self, query):
return [(id, self.items[id]['name'], self.items[id]['qty'])
for id in self.items if str(query).upper() in id.upper()]
db = Db()
db.search('pic')
db.search('ure2')
I am having issues with breaking from a multi-line addition to a dictionary. The task requires adding multiple lines of Product,Quantity inputs into a 'Cart' dictionary. The addition to dictionary should stop by a keyword 'show' or something similar which results in printing added elements of the dictionary. I have been able to initiate multi-line inputs to the cart dictionary but can't get the addition to stop by 'show' keyword.
Here's a portion of my code for reference:
class cart():
pcart = {}
def __init__(self,name):
self.name = name
def Show_Cart(self):
print(self.pcart)
def Add_Item(self):
print('Adding your items and quantities')
p,q = input().rpartition(' ')[::2]
while q.lower() != 'show':
self.pcart[p] = q
if q.lower() == 'show':
self.Show_Cart()
My_Cart = cart(input('Name of your cart:'))
print('Choose from the following options:')
status = int(input('1:Add Item 2:Remove Item'))
if status == 1:
My_Cart.Add_Item()
EDIT-
As pointed out by #andrew_reece , the code above wouldnt get to Show_Cart function ever. I then tweaked it a bit and used While True condition to loop over the function operation and use an Else condition to break when 'Show' keyword appears. Here's my final code-
class cart():
pcart = {}
def __init__(self,name):
self.name = name
def Show_Cart(self):
print(self.pcart)
Main()
def Add_Item(self):
print('Adding your items and quantities')
while True:
p,q = input().rpartition(' ')[::2]
if q.lower() != 'show':
self.pcart[p] = q
else:
self.Show_Cart()
break
def Remove_Item(self):
print('Your cart contents are :' ,self.pcart)
print('What all do you want to remove?')
while True:
p = input()
if p.lower() != 'show':
del self.pcart[p]
else:
self.Show_Cart()
break
def Main():
status = int(input('1:Add Item 2:Remove Item'))
if status == 1:
My_Cart.Add_Item()
elif status == 2:
My_Cart.Remove_Item()
My_Cart = cart(input('Name of your cart:'))
print('Choose from the following options:')
Main()
The code now works. However I am still wondering if using While True is a pythonic way to do things?
I have created a class with two functions inside of it. These functions run forever in a loop at the bottom of the code. However, the first function creates a dictionary and the user adds values to this dictionary. The second function is meant to import the dictionary and add 10 to each value. However, when I run this code, I get an error stating that 'Materials is not defined'. How am I supposed to properly use the dictionary in both functions?
Here is my code:
class materialsClass:
def materialsChange(self):
while True:
q1 = raw_input("Type 'edit' to add or change a material, or 'continue' to continue: ")
if q1 == 'edit':
while True:
q2 = raw_input("Type 'add' to add a new material, 'edit' to edit amount of a material: ")
if q2 == 'add':
x = str(raw_input("Enter the Material: "))
y = int(0)
Materials = {x:y}
break
elif q2 == 'edit':
x = str(raw_input("Enter your Material: "))
y = int(raw_input("Enter your Change: "))
Materials[x] += y
break
else:
print "Please Type an Option"
elif q1 == 'continue': break
else:
print "Type an Option!"
print Materials
def materialCounter(self):
for k in Materials: Materials[k] += 10
print Materials
while True:
obj=materialsClass()
obj.materialsChange()
obj.materialCounter()
You cannot use a variable local to a method within another method. You need to define the variable in the class scope and make it an instance variable. For example:
class materialsClass:
def __init__(self):
self.Materials = dict()
def materialsChange(self):
...
self.Materials[x] = y
(in place of Materials = {x:y})
def materialCounter(self):
for k in self.Materials:
self.Materials[k] += 10
print self.Materials
Also note that when the interpreter runs the line
Materials = {x:y}
it replaces the Materials dictionary with a new one and you are not actually adding a new material in the dictionary. That's why you should write:
self.Materials[x] = y
instead. This will add a new material to the dictionary.
Variables inside the functions are in local namespace so you can not use Materials inside the second function as it has been defined in first one ! you can initial Materials in the enclosing class scope instead :
But note that you need to initial your variable inside the __init__ function:
class materialsClass:
def __init__(self):
self.Materials=dict()
def materialsChange(self):
while True:
q1 = raw_input("Type 'edit' to add or change a material, or 'continue' to continue: ")
if q1 == 'edit':
while True:
q2 = raw_input("Type 'add' to add a new material, 'edit' to edit amount of a material: ")
if q2 == 'add':
x = str(raw_input("Enter the Material: "))
y = int(0)
self.Materials = {x:y}
break
elif q2 == 'edit':
x = str(raw_input("Enter your Material: "))
y = int(raw_input("Enter your Change: "))
self.Materials[x] += y
break
else:
print "Please Type an Option"
elif q1 == 'continue': break
else:
print "Type an Option!"
print self.Materials
def materialCounter(self):
for k in self.Materials: self.Materials[k] += 10
print self.Materials
To build on some of the other answers. You have to create a dictionary under the class and the way you were adding items to the dictionary was incorrect so I have changed that. You also have to create a class in the proper way for it to work. I have checked this code and it works for me anyway. I hope this helps.
class materialsClass(object):
def __init__(self): # create a new class
self.materials = {} # create a new dictionary under this class
def materialsChange(self):
while True:
q1 = raw_input("Type 'edit' to add or change a material, or 'continue' to continue: ")
if q1 == 'edit':
while True:
q2 = raw_input("Type 'add' to add a new material, 'edit' to edit amount of a material: ")
if q2 == 'add':
x = str(raw_input("Enter the Material: "))
y = int(0)
self.materials[x] = y # this is how to add items to dictionaries sequentially
print self.materials
break
elif q2 == 'edit':
x = str(raw_input("Enter your Material: "))
y = int(raw_input("Enter your Change: "))
self.materials[x] = y
print self.materials
break
else:
print "Please Type an Option"
elif q1 == 'continue': break
else:
print "Type an Option!"
print self.materials
def materialCounter(self):
for k in self.materials:
self.materials[k] = self.materials[k] + 10
print self.materials
obj=materialsClass() # you do not need to create the class again and again, just once is fine
while True:
obj.materialsChange()
obj.materialCounter()