9

I wanted to create a list that contains x amount of dictionaries all containing the same keys but with different values that's made in a for loop:

Something like

[{'name': Brenda, 'Age': 22, 'Sex': Female},
 {'name': Jorda, 'Age': 32, 'Sex': Male},
 {'name': Richard, 'Age': 54, 'Sex': Male}]

My code is this:

people = []
person = {}

humans = gethumans()

for human in humans:
    number_people, people_data = People.data()
    person['name'] = human.name
    person['age'] = human.age
    person['Sex'] = human.name
    people.append(person)

My output is something like this:

[{'name': Richard, 'Age': 54, 'Sex': Male},
 {'name': Richard, 'Age': 54, 'Sex': Male}
 {'name': Richard, 'Age': 54, 'Sex': Male}]

Since the dictionary values are getting replaced and not added and it's just appending the same dictionary. How can I get around this?

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Rafael Tamayo
  • 362
  • 2
  • 4
  • 15

2 Answers2

8

When you append the dictionary person to the list people you are just appending a reference to the dictionary to the list, so the list ends up containing just references to the SAME dictionary.

Since each time through the loop you overwrite the dictionary with new values, at the end the list contains just references to the last person you appended.

What you need to do is create a new dictionary for every person, for example:

for human in humans:
    number_people, people_data = People.data()
    person = dict()
    person['name'] = human.name
    person['age'] = human.age
    person['Sex'] = human.name
    people.append(person)
Mario Camilleri
  • 1,457
  • 11
  • 24
  • 1
    An important lesson to learn from this very common mistake is that when you assign values to dictionary keys you are overwriting the old values with new ones, BUT when you assign a dictionary to a variable, you are simply reassigning the variable name to a new dictionary object - the old dictionary object still exists, and any references to it are still valid. – Mario Camilleri Oct 07 '18 at 08:56
  • Solved my issue like a charm! Something new that i learnt today! – Mohseen Mulla Jul 23 '21 at 14:36
3

You each time edit the same dictionary, so you do not construct a new one, but edit the old one. Since you each time append the same dictionary to the list, in the end the list contains the same dictionary n times, and all edits are processed on that dictionary.

You thus have to construct a new dictionary in each iteration in the for loop:

people = []
humans = gethumans()

for human in humans:
    number_people, people_data = People.data()
    person = {
        'name': human.name,
        'age': human.age,
        'sex': human.sex
    }
    people.append(person)

I here replaced 'Sex' with 'sex' (since it is strange to have inconsistent key names), and used human.sex instead of human.name.

Here people.data() do not seem to do anything, you can thus use list comprehension here to generate the list:

people = [
    { 'name': human.name, 'age': human.age, 'sex': human.sex }
    for human in humans
]

This will construct a list with all the dictionaries. Given the for loop had no side-effects (this looks to be the case), the above will work.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • 2
    An aside: I stared at this answer for 2 full minutes before I decided that, yes, the word "person" *is* in bold in that code block, and had to look to see how you did that. – Adam Smith Oct 07 '18 at 08:44
  • 1
    @AdamSmith: well I got this trick from a Prolog programmer (mat if I recall correctly). But I do not know who initially started this :). – Willem Van Onsem Oct 07 '18 at 08:57