Python variable dictionary within a dictionary logic understanding issue - python

I'm fairly new to concepts of Python, and practicing with dictionaries. I've a small bidding program where I'm trying to store dictionary within another dictionary as shown below which is not working how I expected:
# Initializing dictionaries
bidder_details = {}
bidders = {}
# Loop for storing bidders details
new_entry = "yes"
ID = 0
while new_entry.lower() == "yes":
name = input("What is your name?: ")
amount = float(input("What's your bid?: "))
ID += 1
# Adding details to bidder_details dictionary
bidder_details["bidder_name"] = name
bidder_details["bid_amount"] = amount
# Adding bidder_details with a key ID code into bidders
bidders[ID] = bidder_details
new_entry = input("Are there any other bidders? Type 'yes' or 'no'\n").lower()
if new_entry not in ("no", "yes"):
print("\nIncorrect input! Taking no new bidders.")
new_entry = "no"
print(f"\n{bidders}")
For multiple loop runs-
My expected output:
{1: {'bidder_name': 'Sam', 'bid_amount': 400.0}, 2: {'bidder_name': 'Ghost', 'bid_amount': 800.0}}
Resulted output:
{1: {'bidder_name': 'Ghost', 'bid_amount': 800.0}, 2: {'bidder_name': 'Ghost', 'bid_amount': 800.0}}
When I tried printing the bidders dictionary within the loop, result is same so I'm a bit confused why it's replacing my old data. Thanks for any help!

The problem is that you are using the same bidder_details dictionary for each bidder, and you're updating its values in each iteration of the loop. Since you're adding the same bidder_details dictionary to the bidder dictionary multiple times, only the last updated version of it is stored in the bidder dictionary, hence all the keys in the bidder dictionary refer to the same bidder_details dictionary.
To fix this, you should create a new bidder_details dictionary inside the while loop, before updating its values, so that each iteration of the loop uses a new bidder_details dictionary.
You can do something like this for the loop:
while new_entry.lower() == "yes":
name = input("What is your name?: ")
amount = float(input("What's your bid?: "))
ID += 1
# Creating a new bidder_details dictionary
bidder_details = {}
# Adding details to bidder_details dictionary
bidder_details["bidder_name"] = name
bidder_details["bid_amount"] = amount
# Adding bidder_details with a key ID code into bidders
bidders[ID] = bidder_details
new_entry = input("Are there any other bidders? Type 'yes' or 'no'\n").lower()
if new_entry not in ("no", "yes"):
print("\nIncorrect input! Taking no new bidders.")
new_entry = "no"

Related

How can I create an input that will loop and create a new list each time?

in case it isn't already obvious im new to python so if the answers could explain like im 5 years old that would be hugely appreirecated.
I'm basically trying to prove to myself that I can apply some of the basic that I have learnt into making a mini-contact book app. I don't want the data to save after the application has closed or anything like that. Just input your name, phone number and the city you live in. Once multiple names are inputted you can input a specific name to have their information printed back to you.
This is what I have so far:
Name = input("enter name here: ")
Number = input("enter phone number here: ")
City = input("enter city here: ")
User = list((Name, Number, City))
This, worked fine for the job of giving python the data. I made another input that made python print the information back to me just to make sure python was doing what I wanted it to:
print("Thank you! \nWould you like me to read your details back to you?")
bck = input("Y / N")
if bck == "Y":
print(User)
print("Thank you! Goodbye")
else:
print("Goodbye!")
The output of this, is the list that the user creates through the three inputs. Which is great! I'm happy that I have managed to make it function so far;
But I want the 'Name' input to be what names the 'User' list. This way, if I ask the user to input a name, that name will be used to find the list and print it.
How do I assign the input from Name to ALSO be what the currently named "User" list
You will need to create a variable which can store multiple contacts inside of it. Each contact will be a list (or a tuple. Here I have used a tuple, but it doesn't matter much either way).
For this you could use a list of lists, but a dictionary will be more suitable in this case.
What is a dictionary?
A dictionary is just like a list, except that you can give each of the elements a name. This name is called a "key", and it will most commonly be a string. This is perfect for this use case, as we want to be able to store the name of each contact.
Each value within the dictionary can be whatever you want - in this case, it will be storing a list/tuple containing information about a user.
To create a dictionary, you use curly brackets:
empty_dictionary = {}
dictionary_with_stuff_in_it = {
"key1": "value1",
"key2": "value2"
}
To get an item from a dictionary, you index it with square brackets, putting a key inside the square brackets:
print(dictionary_with_stuff_in_it["key1"]) # Prints "value1"
You can also set an item / add a new item to a dictionary like so:
empty_dictionary["a"] = 1
print(empty_dictionary["a"]) # Prints 1
How to use a dictionary here
At the start of the code, you should create an empty dictionary, then as input is received, you should add to the dictionary.
Here is the code I made, in which I have used a while loop to continue receiving input until the user wants to exit:
contacts = {}
msg = "Would you like to: \n - n: Enter a new contact \n - g: Get details for an existing contact \n - e: Exit \nPlease type n, g, or e: \n"
action = input(msg)
while action != "e":
if action == "n": # Enter a new contact
name = input("Enter name here: ")
number = input("Enter phone number here: ")
city = input("Enter city here: ")
contacts[name] = (number, city)
print("Contact saved! \n")
action = input(msg)
elif action == "g": # Get details for an existing contact
name = input("Enter name here: ")
try:
number, city = contacts[name] # Get that contact's information from the dictionary, and store it into the number and city variables
print("Number:", number)
print("City:", city)
print()
except KeyError: # If the contact does not exist, a KeyError will be raised
print("Could not find a contact with that name. \n")
action = input(msg)
else:
action = input("Oops, you did not enter a valid action. Please type n, g, or e: ")
#can be easier to use with a dictionary
#but its just basic
#main list storing all the contacts
Contact=[]
#takes length of contact list,'int' just change input from string to integer
contact_lenght=int(input('enter lenght for contact'))
print("enter contacts:-")
#using for loop to add contacts
for i in range(0,len(contact_lenght)):
#contact no.
print("contact",i+1)
Name=input('enter name:')
Number=input('enter number:')
City=input("enter city:")
#adding contact to contact list using .append(obj)
Contact.append((Name,Number,City))
#we can directly take input from user using input()
bck=input("Thank you! \nWould you like me to read your details back to you?[y/n]:")
#checking if user wants to read back
if bck=='y':
u=input("enter your name:")
#using for loop to read contacts
for i in range(0,len(Contact)):
#if user name is same as contact name then print contact details
if u==Contact[i][0]:
print("your number is",Contact[i][1])
print("your city is",Contact[i][2])
else:
#if user doesnt want to read back then print thank you
print("Good bye")
For this purpose you should use a dictionary.
The key of every entry should be the string 'User[0]' that corresponds to the person's name.
The contents of every entry should be the list with the information of that user.
I'll give you an example:
# first we need to create an empty dictionary
data = {}
# in your code when you want to store information into
# the dictionary you should do like this
user_name = User[0] # this is a string
data[user_name] = User # the list with the information
If you want to access the information of one person you should do like this:
# user_you_want string with user name you want the information
data[user_you_want]
Also you can remove information with this command:
del data[user_you_want_to_delete]
You can get more information on dictionaries here: https://docs.python.org/3/tutorial/datastructures.html#dictionaries
You should start by defining a class to support name, phone and city. Once you've done that, everything else is easy.
class Data:
def __init__(self, name, city, phone):
self.name = name
self.city = city
self.phone = phone
def __eq__(self, other):
if isinstance(other, str):
return self.name == other
if isinstance(name, type(self)):
return self.name == other.name and self.city == other.city and self.phone == other.phone
return False
def __str__(self):
return f'Name={self.name}, City={self.city}, Phone={self.phone}'
DataList = []
while (name := input('Name (return to finish): ')):
city = input('City: ')
phone = input('Phone: ')
DataList.append(Data(name, city, phone))
while (name := input('Enter name to search (return to finish): ')):
try:
print(DataList[DataList.index(name)])
except ValueError:
print('Not found')

How do I take a dictionary from one function and use it in another in python?

Edit: changing code as the issue came up first somewhere else in my code
I'm trying to figure out how to use my dictionary from one function in another one and the other answers on here haven't helped.
The overall goal is to print the key and value just entered into the dictionary named contacts but contacts can only be defined inside init_phonebook
def init_phonebook():
contacts = {}
while True:
choice = print_menu()
if choice == 1:
list_contacts(contacts)
elif choice == 2:
add_contact(contacts)
elif choice == 3:
find_contact(contacts)
elif choice == 4:
edit_contact(contacts)
elif choice == 5:
delete_contact(contacts)
elif choice == 6:
delete_all(contacts)
elif choice == 7:
thanks()
Down here the issue is that .keys and .values don't work as it's not recognizing contacts as a dictionary. I've tried changing the parameter to something else but it doesn't work that way either.
def add_contact(contacts):
phone_number = input('Please enter a phone number: ')
name = input('What would you like to save the name as?: ')
if name in contacts:
print('This contact already exists in your phonebook')
elif name not in contacts:
contacts[name] = phone_number
print('Contact successfully saved')
print('Your updated phonebook is shown below')
for c in contacts:
print('{} --> {}'.format(contacts.keys(c), contacts.values(c)))
print()
the error message I get is:
File "c:\Users\myname\Desktop\VS Code Projects\contact_list.py", line 54, in add_contact
print('{} --> {}'.format(contacts.keys(c), contacts.values(c)))
TypeError: dict.keys() takes no arguments (1 given)
The problem is not how you go about passing the dictionary to these other functions.The error actually arising within your add_contact() function, due to how you are trying to iterate through the dictionary key-val pairs:
for c in contacts:
print('{} --> {}'.format(contacts.keys(c), contacts.values(c)))
It seems you want to iterate through the contacts. contact.keys() does not let you access/index a key, this method returns all of the keys in a dict. contact.values does not let you access/index a value, it returns all of the values in the dict. When you call "for c in contacts", c represents a key. So here are two alternative ways to iterate through:
Properly indexing on the contacts dict using the key c:
for c in contacts:
print('{} --> {}'.format(c, contacts[c]))
By iterating through both the key and value pairs:
for key,value in contacts.items():
print('{} --> {}'.format(key, value))
If confused about a type in Python, I recommend referring to the documentation!
dict.keys() and dict.values() both return arrays that can be indexed but accepts no inputs when called.
But in your case, since you are looping over the dictionary, each iteration stores the key in c. In your case that will be the name associated with the contact.
So you already have the key stored in c on each iteration. What you need next is to use the key to get the value like so dict[key] or dict.get(key).
Alternatively, you can loop over both keys and values simultaneously like so:
for name, phone_number in contacts:
print("{} ==> {}".format(name, phone_number))
I am altering your original code as follows:
def add_contact(contacts):
phone_number = input('Please enter a phone number: ')
name = input('What would you like to save the name as?: ')
if name in contacts:
print('This contact already exists in your phonebook')
else: #You seem to have only two options so no need for elif
contacts[name] = phone_number
print('Contact successfully saved')
print('Your updated phonebook is shown below')
for c in contacts: #c will hold name in each iteration
print('{} --> {}'.format(c, contacts[c]))

check if key or value exists from one input

I have a dictionary that is similar to
my_dict ={'Bob' : 11, 'Sandy':12, 'Katy':13}
and I have a code that checks if the input matches the value
user_input = input('Enter a name')
while my_dict.get(user_input) == None:
chosenSchool = input('please enter a correct name')
and then other code happens
so that works out fine, but Im trying to have code commence if the user has typed the correct value from user_input, i tried something like this, and i made a list of both the keys and values from my_dict, person_name, and person_code.
if user_input.isdecimal():
while user_input not in my_dict.values():
chosenSchool = input("enter a correct name or number")
numval = int(user_input)
pos_of_Name = person_code.index[numval]
Name_person = person_name[pos_of_name]
So eventually the name of this person should be Name_person, and the code numval, but clearly I am doing something wrong. I could probably make a function or something as well

Python Grocery List Python 3 Codio Challenge

So I am looking for a way to add separate items to a list in the form of individual dictionaries that contain the grocery item's name, price, and quantity. I only started programming a few weeks ago so please forgive my horrendous code and beginner mistakes.
grocery_item = dict()
current_item = dict()
grocery_history = []
choice = 0
stop = True
while stop == True:
current_item['name'] = str(input('Item name: '))
current_item['quantity'] = int(input('Amount purchased: '))
current_item['cost'] = float(input('Price per item: '))
grocery_history.append(current_item)
choice = str(input('Press c to continue or q to quit'))
if choice == 'c':
stop = True
else:
stop = False
print(grocery_history)
When I input the information of two items (ie spam and eggs) I get the following output:
[{'name': 'Eggs', 'quantity': 12, 'cost': 1.5}, {'name': 'Eggs', 'quantity':
12, 'cost': 1.5}]
Instead of creating two different items the output just repeats the most recent one I entered. I am making some basic semantic error and I can't figure out how to populate the "grocery_history" list with different items from the user input loop. I tried using pythontutor.com for help but was just berated for being stupid. Any help is appreciated.
Try doing this:
grocery_item = dict()
grocery_history = []
choice = 0
stop = True
while stop == True:
current_item = dict()
current_item['name'] = str(input('Item name: '))
current_item['quantity'] = int(input('Amount purchased: '))
current_item['cost'] = float(input('Price per item: '))
grocery_history.append(current_item)
choice = str(input('Press c to continue or q to quit'))
if choice == 'c':
stop = True
else:
stop = False
print(grocery_history)
By creating a new dictionary in each loop you'll avoid the duplicate error that you're seeing.
You should move the current_item dictionary into the while, for example:
while True:
current_item = {}
# accepts user inputs here
grocery_history.append(current_item)
choice = str(input('Press c to continue or q to quit'))
if choice != 'c':
break
Some other notes:
No need to initiate choice = 0 before the loop.
Use break to stop the loop as soon as possible without going back to check the condition again
You're getting this because dictionaries in Python are mutable objects: this means that you can actually modify their fields without creating a brand new one.
Follow this link if you want to understand more deeply what are the main differences between mutable and immutable objects.
This is your code slightly modified, and working:
grocery_history = []
while True:
name = input('Item name: ').strip()
quantity = int(input('Amount purchased: '))
cost = float(input('Price per item: '))
current_item = {'name':name, 'quantity':quantity, 'cost':cost}
grocery_history.append(current_item)
choice = str(input('Press c to continue or q to quit: '))
if choice == 'q':
break
print(grocery_history)

Mutate a list within a dictionary

I'm new to the dictionary concept and am stuck at a problem. I have compiled a dictionary for a bookstore, and within the dictionary the key is the author's last and first name, ie. 'Shakespeare,William'.
{'Dickens,Charles': [['Hard Times', '7', '27.00']],
'Shakespeare,William': [['Rome And Juliet', '5', '5.99'],
['Macbeth', '3', '7.99']]}
Values are: book name, quantity on hand, and price. I want a function that can change the quantity of the book.
The user will enter: the author's last name, then first, and then the name of the book, and then the new quantity they want.
If the author does not exist it should say that there isn't an author by the name given, and same thing if the book doesn't exist.
In a separate function, I need to add up the total quantity of this inventory. So as seen right now, it would be 5+3+7 = 15 books. I need a similar function for the price, but it should be essentially the same as that of the quantity I believe.
Thank you for your help.
I tried creating another dictionary with the books as the keys as follow:
def addBook(theInventory):
d = {}
first = input("Enter the first name: ")
last = input("Enter the last name: ")
first = first[0].upper() + first[1:].lower()
last = last[0].upper() + last[1:].lower()
name = last + "," + first
book = input("Enter the name of the book: ")
for name, books in sorted(theInventory.items()):
for title, qty, price in sorted(books):
d[title] = []
d[title].append(qty)
d[title].append(price)
d[book][0] = qty
I need to update theInventory with the new quantity, so theInventory would change in main(), but this isn't doing it. How can I make it so that d is referencing theInventory and changing the qty in there?
I think I came up with something like what you want. One problem I ran into was how you formatted your dictionary. In your original post, you had double lists for all dictionary values. I think it would be easier to format the dictionary like I did. One change I made to keep in mind is that in the changeQuantity() function, I switched the inventory number from a string to an int value. I'm not sure how you want to it be, but the format can easily be changed by making the newquant arg a string type. Hope this helped!
bookdict = {'Dickens,Charles': ['Hard Times', '7', '27.00'],
'Shakespeare,William': [['Rome And Juliet', '5', '5.99'], ['Macbeth', '3', '7.99']]}
def changeQuantity(authorlast,authorfirst,bookname,newquant):
bookfound = False
author = str(authorlast)+','+str(authorfirst)
if not author in bookdict:
return "Author not in inventory"
temp = bookdict.values()
if type(bookdict[author][0]) == list:
for entry in bookdict[author]:
if entry[0] == bookname:
entry[1] = newquant
bookfound = True
else:
if bookdict[author][0] == bookname:
bookdict[author][1] = newquant
bookfound = True
if bookfound == False:
return "Book not in author inventory"
return bookdict
def sumInventory():
sum = 0
for key in bookdict.keys():
if type(bookdict[key][0]) == list:
for entry in bookdict[key]:
sum += int(entry[1])
else:
sum += int(bookdict[key][1])
return sum
print changeQuantity("Dickens","Charles","Hard Times",2)
print changeQuantity("a","b","Hard Times",2)
print changeQuantity("Shakespeare", "William", "a", 7)
print sumInventory()
Output:
{'Shakespeare,William': [['Rome And Juliet', '5', '5.99'], ['Macbeth', '3', '7.99']], 'Dickens,Charles': ['Hard Times', 2, '27.00']}
Author not in inventory
Book not in author inventory
10

Categories