0

I want to take input from the user and initialize a list of dictionaries. I have the following block which works fine.

people = []

for p in range(3):
    cell = {"name": "","age" : 0, "education" : "","height" : 0}
    cell["name"] = input("name:")
    cell["age"] = int(input("age:"))
    cell["education"] = input("education:")
    cell["height"] = float(input("height:"))
    people.append(cell)

The problem I have is why the following block does not work for me.

people = []

cell = {"name": "","age" : 0, "education" : "","height" : 0}
for p in range(0,3):
    cell["name"] = input("name:")
    cell["age"] = int(input("age:"))
    cell["education"] = input("education:")
    cell["height"] = float(input("height:"))
    people.append(cell)

I do not understand why at the end of the iteration I have the list initialized with the latest input all the 3 times, I mean when I use this line:

cell["name"] = input("name:")

shouldn't the previous value been replaced with the new one?

Mushroom Man
  • 400
  • 3
  • 18
theVoid
  • 743
  • 4
  • 14
  • You keep modifying the same `cell` object and appending it to the `people` list. – PM 2Ring May 31 '16 at 19:42
  • 1
    On a closely-related note: http://stackoverflow.com/questions/240178/python-list-of-lists-changes-reflected-across-sublists-unexpectedly – PM 2Ring May 31 '16 at 19:55

3 Answers3

4

The important part is this line:

cell = {"name": "","age" : 0, "education" : "","height" : 0}

here you create a dictionary and save a reference to it under cell

If you do this before the loop (like in your second example) you have only created one dictionary and appended it to the list three times. So if you change anything inside of any dictionary, your changes will show up at all indices of the list (since they all point to the same dictionary)

However, if you run the line inside of your loop you actually create three different dictionaries, which is essentially what you want here. This is why your first example works and your second one doesn't.

Keiwan
  • 8,031
  • 5
  • 36
  • 49
  • So the changes i make during the loop affect and the cells that i have allready appended to the list? – theVoid May 31 '16 at 19:47
  • 2
    Yes, because there are only `references` to dictionaries inside of your list. So in your second code you 1. create a dictionary 2. change its values 3.append a reference to it to the list 4. change the values of the same dictionary again 5. append the **same** reference to the same dictionary to the list... – Keiwan May 31 '16 at 19:49
1

This is the difference between passing by value and passing by reference. Passing by reference, or a pointer in other language terms, means the variable points to a spot in memory. In Python, dictionaries behave this way, which means that since you are, in the second version, changing what exists in the dictionary then appending it, what you are actually doing is appending the SAME dictionary to the array a second (and third) time. Between each of those times, it happens to change its values, but when you look at the array at the end, the SAME updated dictionary shows up three times.

In the first example, you are instantiating a new copy of the cell variable each loop, which results in a different memory location. It is fundamentally a DIFFERENT dictionary each time, which in this case, gives you the result you are looking for.

Brian Mego
  • 1,439
  • 11
  • 10
  • 2
    In python there isn't really the concept of "passing by value" or "passing by reference". In python everything is "passed by reference". – syntonym May 31 '16 at 19:53
1

shouldn't the previous value been erased and the new one to take it's place?

No! This is because every loop modifies the same object since the reference is not changing. This is why you have the last iteration values showing up three times.

Try:

for p in range(0,3):
    cell = {"name": "","age" : 0, "education" : "","height" : 0}
    cell["name"] = input("name:")
    cell["age"] = int(input("age:"))
    cell["education"] = input("education:")
    cell["height"] = float(input("height:"))
    people.append(cell)
UltraInstinct
  • 43,308
  • 12
  • 81
  • 104