Update value of object in list - python

I have several lists that each contain objects. All objects have the values "name" and "amount". What I want to do is create a method to update "amount" by first finding the item in the list by user input (enter name to find name) then adding or subtracting a user input value (enter value to add/enter value to subtract).
How would I go about doing this?
This is what I have so far (It's incomplete but it's all I could get done):
Containers = []
Lids = []
Wicks = []
Labels = []
Misc = []
class item(object):
#Constructor
def __init__(self, name, amount):
self.name = name
self.amount = amount
#Accessors
def getName(self):
return self.name
def getAmount(self):
return self.amount
#Mutators
def __str__(self):
return "[Name: " + self.name + \
", Amount: " + self.amount + \
"]"
def addAmount():
found = False
name = input("Enter the name of a container you wish to change: ")
addNewAmount = input("Enter the amount you wish to add: ")
for item in Containers:
if name in item.getName():
found = True
position = Containers.index(name)
print(Containers[position])
if not found:
print("No names match that input.")
def subtractAmount():
update = input("Enter a new amount to subtract: ")
self.amount = amount - update
def addContainer():
name = input("Enter a name for the new container: ")
amount = input("Enter an amount for the new container: ")
return item(name, amount)
def addLid():
name = input("Enter a name for the new lid: ")
amount = input("Enter an amount for the new lid: ")
return item(name, amount)
def addWick():
name = input("Enter a name for the new wick: ")
amount = input("Enter an amount for the new wick: ")
return item(name, amount)
def addLabel():
name = input("Enter a name for the new label: ")
amount = input("Enter an amount for the new label: ")
return item(name, amount)
def addMisc():
name = input("Enter a name for the new misc item: ")
amount = input("Enter an amount for the new misc item: ")
return item(name, amount)
def main():
running = True
while running:
print("Enter a number to start.")
print("1) Add new container 2) Add new lid")
print("3) Add new wick 4) Add new label")
print("5) Add new misc Item 6) Print Inventory")
print("7) Add Amount from item 8) Subtract Amount from item")
print("10) quit")
print("11) print list")
choice = input("> ")
if choice == "1":
Containers.append(addContainer())
elif choice == "2":
Lids.append(addLid())
elif choice == "3":
Wicks.append(addWick())
elif choice == "4":
Labels.append(addLabel())
elif choice == "5":
Misc.append(addMisc())
elif choice == "6":
print("<==========Containers==========>")
for i in Containers:
print(i)
print("<=============Lids=============>")
for i in Lids:
print(i)
print("<=============Wicks============>")
for i in Wicks:
print(i)
print("<============Labels============>")
for i in Labels:
print(i)
print("<==========Misc Items==========>")
for i in Misc:
print(i)
elif choice == "7":
return addAmount()
elif choice == "8":
return subtractAmount()
elif choice == "10":
quit()
elif choice == "11":
print('[%s]' % ', '.join(map(str, Containers)))
else:
print("Invalid entry, please try again.")
if __name__ == "__main__":
main()

There's a couple of issues here. The first is whether you want containers, lids, wicks, etc to all be the same type of object ("item") or whether it would make more sense to have subclasses. Assuming you want them all to be the same ("item") you could adjust your methods according to the code below (I've left out a lot of options for simplicity).
A couple things to note:
"amount" needs to be numerical (int) in order to add or subtract from it correctly
the creation of an item is a function outside the class, and allocates the item to the appropriate list (Containers, Lids)
the "add_amount" function looks through all lists of all items to find a possible match and adjusts the amount accordingly. If a lid and container have the same name, it will modify the first match.
Containers = []
Lids = []
Items = [Containers, Lids]
class item(object):
#Constructor
def __init__(self, name, amount):
self.name = name
self.amount = amount
#Accessors
def getName(self):
return self.name
def getAmount(self):
return self.amount
def __str__(self):
return "[Name: " + self.name + \
", Amount: " + str(self.amount) + \
"]"
def addItem():
global new_item
name = input("Enter a name for the new item: ")
amount = int(input("Enter an amount for the new item: "))
new_item = item(name, amount)
return new_item
def add_amount():
found = False
name = input("Enter the name of the item you wish to change: ")
add_amount = int(input("Enter the amount you wish to add: "))
for itemList in Items:
for item in itemList:
if name == item.getName():
found = True
position = itemList.index(item)
item.amount += add_amount
print(itemList[position])
if not found:
print("No names in match that input.")
def main():
running = True
while running:
print("Enter a number to start.")
print("1) Make a container 2) Make a lid")
print("3) add amount 4) quit")
choice = input("> ")
if choice == "1":
addItem()
print new_item.amount
Containers.append(new_item)
elif choice == "2":
addItem()
print new_item.amount
Lids.append(new_item)
elif choice == "3":
add_amount()
elif choice == "4":
quit()
else:
print("Invalid entry, please try again.")
if __name__ == "__main__":
main()

This might be kind of messy, but should do the work:
def subtractAmount():
containers = [Containers, Lids, Wicks, Labels, Misc]
names = ['Containers', 'Lids', 'Wicks', 'Labels', 'Misc']
print('Select the number of list you want to search for item')
print('\n'.join('{}) {}'.format(str(idx), lst_name) for (idx, lst_name) in enumerate(names, 1)))
selected = input(': ')) - 1
item_name = input('Enter the item name you are looking for: ')
item = None
for value in containers[selected]:
if value.getName().lower() == item_name.lower():
item = value
break
else:
print('No item was found with that name!')
new_amount = input('Enter the new amount for item: ')
item.amount = new_amount

Related

Unable to pass/exit a python function

Just starting out with python functions (fun_movies in functions.py) and I can't seem to get out (via "no" or False) once in the loop:
main_menu.py
from functions import *
def menu():
print("Press 1 for movies.")
print("Press 2 to exit.")
menu()
option = int(input("Input a number: "))
while option != 0:
#try:
if option == 1:
fun_movies()
elif option == 2:
print("Goodbye! ")
break
else:
print ("Wrong input")
functions.py
global movies
movies = {}
def fun_movies():
name = input("Insert movie name: ")
genre = input("Input genre: ")
movies [name] = [genre]
a = True
while a:
query = input("Do you want to input another movie? (yes/no) ")
if query == "yes":
name = input("Insert movie name: ")
genre = input("Input genre: ")
movies_if = {}
movies_if [name] = [genre]
movies.update(movies_if)
elif query == "no":
break
else:
print ("Wrong input!")
return movies
Code works fine when not called via import. When called via import (in main_menu.py), it keeps asking for infinite movies even when I input a "no". I can't find a way to exit the loop. Initially I had a "pass" but that didn't work.
Thanks in advance!
global movies
movies = {}
def fun_movies():
name = input("Insert movie name: ")
genre = input("Input genre: ")
movies [name] = [genre]
a = True
while a:
query = input("Do you want to input another movie? (yes/no) ")
if query == "yes":
name = input("Insert movie name: ")
genre = input("Input genre: ")
movies_if = {}
movies_if [name] = [genre]
movies.update(movies_if)
elif query == "no":
a = False
else:
print ("Wrong input!")
return movies
A few things:
Firstly, you don't need a==True as this statement returns True when a is True and False when a is False, so we can just use a as the condition.
Secondly, only use the input at the start of the loop as you want to ask once per iteration
Thirdly, place your return outside the loop so you only return when a==False and you don't want to input another movie.
edit:
main file>
from functions import *
def menu():
print("Press 1 for movies.")
print("Press 2 to exit.")
menu()
option = int(input("Input a number: "))
while option != 0:
if option == 1:
fun_movies()
elif option == 2:
print("Goodbye! ")
break
else:
print ("Wrong input")
option = int(input("Input a number"))
global movies
movies = {}
def fun_movies():
name = input("Insert movie name: ")
genre = input("Input genre: ")
movies[name]= genre
a = True
while a:
query = input("Do you want to input another movie? (yes/no) ")
if query == "yes":
name = input("Insert movie name: ")
genre = input("Input genre: ")
movies_if = {}
movies_if [name] = genre
movies.update(movies_if)
elif query == "no":
break
else:
print ("Wrong input!")
# continue
return movies
print(fun_movies())
Hope It works for you!

How to check String input from user inside Class Array

I'm working on an exercise, but I'm stuck on the last part
The section goes here:
Rewrite the function remove_friend so it asks for both the firstname and the lastname and remove all in the list_of_friends for which the first- and last name of the friend object equals the first- and last name entered by the user
In the remove_friends function, I know it's not correct.
In my head, I think I need to compare the delete_first_name and delete_last_name against the first_name and last_name in the new_friends class.
However, I don't know what the syntax would be in order to accomplish this.
Does anyone have hints on how to proceed? I would greatly appreciate if you could give suggestions, and not write the solution.
class Friend:
def __init__(self, first_name, last_name, phone_number):
self.first_name = first_name
self.last_name = last_name
self.phone_number = phone_number
def print_info(self, index):
print(f"\n {self.first_name}, {self.last_name}, {self.phone_number} \n")
list_of_friends = []
def add_friends():
print(" ")
first_name = input("Enter the first name: ")
last_name = input("Enter the last name: ")
phone_number = input("Enter the phone number: ")
new_friend = Friend(first_name.upper(), last_name.upper(), phone_number)
list_of_friends.append(new_friend)
print(f"{new_friend.first_name.title()} {new_friend.last_name.title()} has been added to the list \n")
def view_friends():
if len(list_of_friends):
for counter, new_friend in enumerate(list_of_friends, 0):
print(" ")
new_friend.print_info(counter)
else:
print(" ")
print("List is empty \n")
def remove_friends():
print(" ")
delete_first_name = input("Enter first name to remove: ").upper()
delete_last_name = input("Enter last name to remove: ").upper()
full_name = [delete_first_name, delete_last_name]
if full_name not in list_of_friends:
print(f"{delete_first_name} {delete_last_name} does not exist in the list \n")
else:
list_of_friends.remove(delete_first_name)
list_of_friends.remove(delete_last_name)
print(f"{delete_first_name} {delete_last_name}has been deleted from the list \n")
def print_menu():
menu_string = "\n----Options----\n"
menu_string += "1: Add\n"
menu_string += "2: View\n"
menu_string += "3: Remove\n"
menu_string += "4: Exit\n"
print(menu_string)
user_input = 0
while user_input != 4:
print_menu()
try:
user_input = int(input("Choose one of the above options: "))
if user_input < 1 or user_input > 4:
print("Invalid number. Number must be between 1-4 \n")
elif user_input == 1:
add_friends()
elif user_input == 2:
view_friends()
elif user_input == 3:
remove_friends()
except Exception as err:
print(f"Invalid input: {err}")
print("Exiting \n")
Loop the the list of friends and check first and last name
def remove_friends():
print(" ")
delete_first_name = input("Enter first name to remove: ").upper()
delete_last_name = input("Enter last name to remove: ").upper()
new_list = []
for frnds in list_of_friends:
fnm = frnds.first_name
lnm = frnds.last_name
if(fnm == delete_first_name and lnm == delete_last_name):
# print something meaningfull
continue
else:
new_list.append(frnds)
# new_list will contain the list of friends after removal
The list list_friends has Friend objects and not strings.
you need to access the Friend attributes.
for example like this (function is not complete):
def remove_friends():
first_name=...
last_name = ...
temp_list = list_of_friends[:]
for friend in temp_list :
if first_name == friend.first_name and last_name == friend.last_name:
list_of_friends.remove(friend)
Note that in the beginning I copied the list - do not iterate over a list (or similar) and delete objects from the same list, it is a recipe for bugs.

Python Pulling from Datasheets

I am trying to create code to pull from a data sheet. My goal is to find the longest song, songs by year, and songs by an artist. Problem is, that when I run what I currently have I get a value returned of 0. Obviously this is not correct. What ways can I do to solve this? I have linked the data sheet here. Click here!
def longest_song():
pass
def songs_by_year(year):
total=0
with open('music.csv', 'r') as f:
for line in f:
time = line.split(",")
song = time[34]
if song == year:
total = total + 1
return total
def all_songs_by_artist(artist):
total = int(0)
data = open("music.csv", "r")
for line in data:
name = line.split(",")
song = name[2]
if song == artist:
total = total + 1
return total
# --------------------------------------
def menu():
print()
print("1. Identify longest song.")
print("2. Identify number of songs in a given year.")
print("3. Identify all songs by a given artist.")
print("4. You choose something that is interesting and non-trivial.")
print("5. Quit.")
# --------------------------------------
def main():
choice = 0
while (choice != 5):
menu()
choice = int(input("Enter your choice: "))
if (choice == 1):
longest_song()
elif (choice == 2):
year = int(input("Enter desired year: "))
number = songs_by_year(year)
## print("The number of songs from", "{:,d}".format(number))
print(number)
elif (choice == 3):
artist = input("Enter name of artist: ").lower()
all_songs_by_artist(artist)
number = all_songs_by_artist(artist)
print("There are", "{:,d}".format(number))
elif (choice == 4):
pass
elif (choice != 5):
print("That is not a valid option. Please try again.")
# --------------------------------------
main()
You are converting input artist to lowercase but Not changing the artist from the file to lower case, thus no matches.
You are converting the Year to an int but not doing so to the year from the file.
It is difficult to tell if there are other issues, as your code sample is not indented properly.
I'm guessing but I suppose that it should look something like this.
def longest_song(): pass
def songs_by_year(year):
total=0
with open('music.csv', 'r') as f:
for line in f:
time = line.split(",")
song = time[34]
try:
if int(song) == year:
total = total + 1
except:
pass
return total
def all_songs_by_artist(artist):
total = int(0)
with open("music.csv", "r") as data:
for line in data:
name = line.split(",")
song = name[2].lower()
if song == artist:
total = total + 1
return total
# --------------------------------------
def menu():
print()
print("1. Identify longest song.")
print("2. Identify number of songs in a given year.")
print("3. Identify all songs by a given artist.")
print("4. You choose something that is interesting and non-trivial.")
print("5. Quit.")
# --------------------------------------
def main():
choice = 0
while (choice != 5):
menu()
choice = int(input("Enter your choice: "))
if (choice == 1):
longest_song()
elif (choice == 2):
year = int(input("Enter desired year: "))
number = songs_by_year(year)
## print("The number of songs from", "{:,d}".format(number))
print(number)
elif (choice == 3):
artist = input("Enter name of artist: ").lower()
all_songs_by_artist(artist)
number = all_songs_by_artist(artist)
print("There are", "{:,d}".format(number))
elif (choice == 4):
pass
elif (choice != 5):
print("That is not a valid option. Please try again.")
# --------------------------------------
main()

Mimic a phone book

I am trying to create a code that mimics a phone book.
I want the program to accept a last name, a first name or a phone number from the user and to read through the text file/list, looking for a match. If match(s) are found, display the information, and then redisplay the menu.
If the entry was not found display the appropriate not found message. All search results will be written to the screen.
def main():
firstname=[]
lastname=[]
phone=[]
loadLists(firstname, lastname, phone)
choice = menu()
while choice != '4':
if choice == '1':
getLastName(firstname, lastname, phone)
elif choice == '2':
getFirstName(firstname, lastname, phone)
elif choice == '3':
getPhone(firstname, lastname, phone)
choice = menu()
def loadLists(firstname, lastname, phone):
myFile="entries.txt"
fileInput=open(myFile)
count = 0
for myString in fileInput:
myString = myString.strip()
myString = myString.lower()
myNum = count % 3
if myNum == 0:
lastname.append(myString)
elif myNum == 1:
firstname.append(myString)
elif myNum == 2:
phone.append(myString)
count = count +1
fileInput.close()
def menu():
option = '0'
while option != '1' and option != '2' and option != '3' and option != '4':
print("\n1. Look up contact by last name")
print("2. Look up contact by first name")
print("3. Look up contact by phone number")
print("4. Quit")
option = input("\nMenu option: ")
if option != '1' and option != '2' and option != '3' and option != '4':
print("Invalid option. Please select again.")
return option
def getLastName(firstname, lastname, phone):
target=input("\nEnter contacts last name: ")
target=target.strip().lower()
position=0
if target in lastname:
while True:
try:
position=lastname.index(target, position)
entry =firstname[position].title()+" "+lastname[position].title()+" "+phone[position].title()
print("\n" + entry)
position= position + 1
except:
break
else:
print("\nNot found")
def getFirstName(firstname, lastname, phone):
target=input("\nEnter contacts first name: ")
target=target.strip().lower()
position=0
if target in firstname:
while True:
try:
position=firstname.index(target, position)
entry=firstname[position].title()+" "+lastname[position].title()+" "+phone[position].title()
print("\n" + entry)
position= position + 1
except:
break
else:
print("\nNot found")
def getPhone(firstname, lastname, phone):
target=input("\nEnter contacts phone number: ")
target=target.strip().lower()
position=0
if target in phone:
while True:
try:
position=phone.index(target, position)
entry=firstname[position].title()+" "+lastname[position].title()+" "+phone[position].title()
print("\n" + entry)
position=position + 1
except:
break
else:
print("\nNot found")
main()
When I run the program it won't load the file I have assigned 'entries.txt'. Could someone explain to me why? I have the file saved to my computer as 'entries' and i've double checked that it is a txt file.
You're not even getting into the loop in loadList, since fileInputis a pointer to a file. Try for myString in fileInput.readlines(): instead.
Instead of using:
def loadLists(firstname, lastname, phone):
myFile="entries.txt"
fileInput=open(myFile)
count = 0
Try using:
def loadLists(firstname, lastname, phone):
myFile="entries.txt"
fileInput=open(myFile, "r")
count = 0

Why wont my code load properly?

In class we have to create a save/load function utilizing the split() method for a class and dictionary. I managed to get the save function working, but the load function does not seem to want to work for me. I either get it almost working but the saved file does not load, or i get the error
"playerclass" has no "player" attribute. needs to use the init method. Here is the code in its entirety def loaddata(): is mainly the area of concern.
class playerclass:
name = ""
phone = ""
jersey = ""
def __init__(self, name, phone, jersey):
self.name = name
self.phone = phone
self.jersey = jersey
def setname(self, name):
self.name = name
def setphone(self, phone):
self.phone = phone
def setjersey(self, jersey):
self.jersey = jersey
def getname(self):
return self.name
def getphone(self):
return self.phone
def getjersey(self):
return self.jersey
def disroster(self):
print("Player Bio")
print("-----------")
print("Name: ", self.name)
print("Phone #: ", self.phone)
print("Jersey #: ", self.jersey)
def savedata (players):
filename = input("Enter file name: ")
print("Saving....")
outFile = open(filename, "wt")
for x in players.keys():
name = players[x].getname()
phone = str(players[x].getphone())
jersey = str(players[x].getjersey())
outFile.write(name+","+phone+","+jersey+"\n")
print("Save Complete")
outFile.close()
def loaddata ():
players = {}
filename =input("Enter filename to load: ")
inFile = open(filename, "rt")
print("Loading.....")
while True:
inLine = inFile.readline()
if not inLine:
break
inLine = inLine [:-1]
name, phone, jersey = inLine.split(",")
players[name] = playerclass(name, phone, jersey)
print("Load Successfull.")
inFile.close()
return players
def roster(players):
if len(players) == 0:
print("No players on roster: ")
else:
for x in players.keys():
players[x].disroster()
def add_player (players):
newName=input("Enter name of player to add: ")
newPhone = int(input("Enter phone number of player: "))
newJersey = int(input("Enter number of assigned jersey: "))
players[newName]= playerclass(newName, newPhone, newJersey)
return players
def ed_player (players):
oldName = input("Enter players name to edit: ")
if oldName in players:
newName = input("Enter new name for player: ")
newPhone = int(input("Enter new phone number for player: "))
newJersey = int(input("Enter newly assigned jersey number: "))
players[oldName] = playerclass(newName, newPhone, newJersey)
return players
def del_player(players):
delName = input("Enter players name to delete from roster: ")
if delName in players:
del players[delName]
return players
def displayMenu():
print("-------Main Menu-------")
print("1. Display Team Roster.")
print("2. Add Member.")
print("3. Remove Member.")
print("4. Edit Member.")
print("5. Save Data.")
print("6. Load Data.")
print("9. Exit Program.")
return input("Menu Choice: ")
print("Team Management Tools.")
players = {}
menu_choice = displayMenu()
while menu_choice != '9':
if menu_choice == '1':
roster(players)
elif menu_choice == '2':
players = add_player (players)
elif menu_choice == '3':
players = del_player (players)
elif menu_choice == '4':
players = ed_player (players)
elif menu_choice == '5':
savedata (players)
elif menu_choice == '6':
loaddata ()
menu_choice = displayMenu()
print("Updating roster Goodbye:")
Remove players = {} from your loaddata function, and it'll load properly.
If you actually want to reset the contents of the dictionary when loading (which might have been your intent, although I would say that's a questionable design decision), you can do:
def loaddata():
global players
players = {}
...
This is because any variables you write to are assumed to be local variables (as in, local to the function) unless you say otherwise.
I might be overlooking something, but I'm not seeing anything that attempts to read a player attribute from any object, so I'm not sure where the error is coming from. Was it from a different version of this code? Or, if it is the posted version that has that error, can you provide exactly what series of inputs lead to the error?
The rest of this answer isn't directly relevant to your question, just some tips based on things I noticed in your code.
I would remove the:
name = ""
phone = ""
jersey = ""
Because you set them in __init__ and so they're redundant and not doing anything. For looping over lines in files, you can use a for loop, which is more readable than while loops. Example:
for line in infile:
print(line)
And you should look into with. It's another type of block, and they're very useful when working with files because they'll automatically close the file when the block ends, so you don't have to. As an example:
with open("foo", "r") as stream:
for line in stream:
print(line)
# stream got implicitly closed because the block ended

Categories

Resources