Editing dictionary value - python

I'm assigning values into a dictionary like this:
contacts = dict()
for company in companies_query:
contacts[company.id] = dict()
for contact in contacts_query:
contacts[contact.company_id][contact.id] = contact
So, for example I now have this key in the contacts dictionary contacts["15"]["10"] assuming there's a company with ID of 15 and a contact with ID of 10.
Now I need to create another for loop to add additional data to these contacts.
for sale in sales_query:
contact = contacts[sale.company][sale.contact]
contact.sale_count += 1
contacts[sale.company][sale.contact] = contact
This doesn't work. For the second line it says there's a KeyError with a value of <Contact: Contact object>. sale.company is in this example 15, and the sale.contact is 10.
How do I edit the dictionary objects?

You are passing in the whole Contact() instance object, not the id attribute value of that object. You probably meant to use:
for sale in sales_query:
contact = contacts[sale.company][sale.contact.id]
e.g. use the sale.contact.id attribute rather than use sale.contact directly.
Since you are manipulating the Contact() instance directly you don't need to assign back to the nested dictionary; the following 3 lines should suffice:
for sale in sales_query:
contact = contacts[sale.company][sale.contact.id]
contact.sale_count += 1
Note that using dict() to create an empty dictionary is not really common or idiomatic. Use the {} literal notation instead:
contacts = {}
for company in companies_query:
contacts[company.id] = {}
for contact in contacts_query:
contacts[contact.company_id][contact.id] = contact
You can build the contacts mapping with a dictionary comprehension too:
contacts = {company.id for company in companies_query}
for contact in contacts_query:
contacts[contact.company_id][contact.id] = contact

Related

Edit list element in multilist - Python

I am using python 3.x, I have the following problem, using the keyboard the user enters certain data and fills N lists to create a contact list, then in a list I collect all the data of the lists, I need to modify the data of each list, (I already have it, I modify the data of a list with a specific value using a for) Example, Names list, I modify Andrew's name, but in the Contacts list, there is all Andrew's information (phone, mail, etc), but I just need to modify in the Contacts list, the value of Andrew
I have all this list:
names = []
surnames = []
phones = []
emails = []
addresses = []
ages = []
salaries = []
genres = []
contacts = []
# and use the append to add the data into the contacts list
contacts.append ([names, surnames, phone numbers, emails, addresses, ages, salaries, genders])
Then I update the info of one contact
search = input(Fore.LIGHTBLUE_EX + "Type the name of the contact you want update: ")
for i in range(len(names)):
if (names[i] == search):
try:
names[i] = input(Fore.MAGENTA + "Type the New name: ")
names[i] = nombres[i].replace(" ", "")
if names[i].isalpha() == True:
print(Fore.GREEN + "Already saved, congrats.")
pause= input(Fore.LIGHTGREEN_EX + "Press enter to exit")
But I dont know how to update the name in the List of contacts.
When you call contacts.append(), you add a list of lists to a list, so your contacts list will look something like this:
contacts = [[[names[0], names[1], ...], [...], [...]]]
It's unnecessary to have a list of one item nested in another list, so I would just call contacts.append() and pass each list (names, surnames, etc.) to the method, which allows for easier indexing.
Since the list names would be the first item in the list contacts (contacts[0]), you could do one of two things (there may be more, but these are off the top of my head):
Reassign the specific index to a new value, using nested-list indexing (contacts[0][0] = "updated name" would update the first item of the names list to "update name")
Reassign the entire nested list to a new list (contacts[0] = new_name_list would reassign contacts[0], formerly the names list, to new_name_list)
On a side note: In this case, I would recommend dictionaries over lists, as it will be easier to keep track of what is being reassigned/modified.
contacts = {
"names": names,
"surnames": surnames,
...
}
Doing this will make it more clear which list your are referring to; contacts[0] doesn't give much information, but contacts["names"] informs readers that you are referring to the names list. This is solely for cleaner code; there isn't much difference in functionality.

Python dictionary data is not getting updated if same dictionary is used again and again

I tried creating a dictionary which holds set of dictionary. For that i did write below.
But since everything is object in python, even though i have assigned new students to dictionary student,
when i print data, i can see only 123 data. Need to understand this behaviour in details and how to over come this problem.
students = {}
student = {}
student['id'] = 123
student['first_name'] = 'Raj'
student['last_name'] = 'Nath'
students[123] = student
student['id'] = 124
student['first_name'] = 'Naveen'
student_1['last_name'] = 'Jain'
students[124] = student
print(students)
In students[123] = student student dictionary is stored under key 123. But it isn't copied. Still under student variable there is the same directory which you are accessing in:
student['id'] = 124
student['first_name'] = 'Naveen'
student_1['last_name'] = 'Jain'
As it is still the same dictionary, you are overriding old values with new values.
If you would like to copy dictionary use:
students[123] = student.copy()
But more accurate would be creating new empty dictionary after assigning:
students[123] = student
student = {}
Python is almost always passing-by-reference to reduce number of operations on memory. You can read more about it here.
The problem here is that you did not create a new dictionary. When you ran the line students[123] = student you passed the dictionary that was stored in the variable student. After that, you then proceeded to modify that same dictionary. I would recommend either creating a copy of the dictionary (students[123] = student.copy()) and storing that in students or creating a new dictionary for each student.
Using copy:
students = {}
student = {}
student['id'] = 123
student['first_name'] = 'Raj'
student['last_name'] = 'Nath'
students[123] = student.copy() # This stores a copy of the dictionary
student['id'] = 124
student['first_name'] = 'Naveen'
student['last_name'] = 'Jain'
students[124] = student
print(students)
Using new dictionary:
students = {}
student = {}
student['id'] = 123
student['first_name'] = 'Raj'
student['last_name'] = 'Nath'
students[123] = student
student = {} # Create a new dictionary to be used for the new student
student['id'] = 124
student['first_name'] = 'Naveen'
student['last_name'] = 'Jain'
students[124] = student
print(students)
Your approach stores many times the same student dictionary into the students one. All the different instances students[0], ..., students[n] in effect point to the same object, that contains the value assigned in the last update you committed.
To make things work, you must instantiate a new dictionary each time you input the data for a new student — I find particularly convenient to use the class constructor in place of the usual literal, but probably it's just me…
students = {}
students[123] = dict(id=123, first_name='Raj', last_name='Nath')
students[124] = dict(id=124, first_name='Naveen', last_name='Jain')
Further, obeying the principle of least duplication, it could be
students = {}
students[123] = dict(first_name='Raj', last_name='Nath')
students[124] = dict(first_name='Naveen', last_name='Jain')
ps1: of course there is also a competing principle of maximum duplication and you should choose the one you prefer ;-)
ps2: id is a Python builtin function, you can assign an integer to id, Python is liberal, but other parts of your program are now in danger of mysteriously breaking…

Dynamically create instances of a class python

I'm new in python and I'm trying to dynamically create new instances in a class. So let me give you an example, if I have a class like this:
class Person(object):
def __init__(self, name, age, job):
self.name = name
self.age = age
self.job = job
As far as I know, for each new instance I have to insert, I would have to declare a variable and attach it to the person object, something like this:
variable = Person(name, age, job)
Is there a way in which I can dynamically do this? Lets suppose that I have a dictionary like this:
persons_database = {
'id' : ['name', age, 'job'], .....
}
Can I create a piece of code that can iterate over this db and automatically create new instances in the Person class?
Just iterate over the dictionary using a for loop.
people = []
for id in persons_database:
info = persons_database[id]
people.append(Person(info[0], info[1], info[2]))
Then the List people will have Person objects with the data from your persons_database dictionary
If you need to get the Person object from the original id you can use a dictionary to store the Person objects and can quickly find the correct Person.
people = {}
for id, data in persons_database.items():
people[id] = Person(data[0], data[1], data[2])
Then you can get the person you want from his/her id by doing people[id]. So to increment a person with id = 1's age you would do people[1].increment_age()
------ Slightly more advanced material below ----------------
Some people have mentioned using list/dictionary comprehensions to achieve what you want. Comprehensions would be slightly more efficient and more pythonic, but a little more difficult to understand if you are new to programming/python
As a dictionary comprehension the second piece of code would be people = {id: Person(*data) for id, data in persons_database.items()}
And just so nothing here goes unexplained... The * before a List in python unpacks the List as separate items in the sequential order of the list, so for a List l of length n, *l would evaluate to l[0], l[1], ... , l[n-2], l[n-1]
Sure, a simple list comprehension should do the trick:
people = [Person(*persons_database[pid]) for pid in persons_database]
This just loops through each key (id) in the person database and creates a person instance by passing through the list of attributes for that id directly as args to the Person() constructor.

Django: get users' IDs with field

I have a model, for example:
class Person(models.Model):
name =
surname =
city =
cars =
I need to get a list of the IDs (primary key auto-set) of the 5 users with the highest number of "cars" with a specific name.
I thought I could do something like:
list = Person.objects.filter(name=name,)('-reputation')[5].id
To get a list of the 5 users with the highest number you can use:
list = Person.objects.filter(name=name).order_by('-reputation')[:5]
to get the ID of each you can use for loop:
for user in list:
userID = user.id
You seem to have missed out the call to order_by.
Person.objects.filter(name=name).order_by('-reputation')[5].id
Using the values_list queryset function can reduce this to a single simple line:
Person.objects.values_list('id', flat=True).filter(name=name).order_by('-reputation')[:5]
and will avoid needing to loop.

Insert only unique objects into list

I have queryset of people:
people = Person.objects.all()
and I have a list un_people = [] - meaning a list of people with unique name.
So, there can be more than one person with the same name. i want to filter for this and then insert into list so that list only contains person objects with unique name.
I tried:
for person in people:
if person.name in un_people:
#... ?
but in list, there are objects, not names. how can I check for objects with same name and then insert into list?
Use a dict to do the uniqueness, then take the values, eg:
uniq_names = {person.name:person for person in people}
uniq_people = uniq_names.values() # use list(unique_names.values()) for Py 3.x
You can use set data structure:
un_people = set(people)
If your elements are not hashable as, JonClemens, suggests you can build a list of names first:
un_people = set([p.name for p in people])

Categories

Resources