1

this is really a puzzle issue, while debugging my code, I found this really strange error (it happened in both python 3.6 and 3.7, have not tested on others)

when I am looping through a simple list, take out the element and assigned in to a dict, creating and new list of dict.

the list.append does not just add on the new element, but it also replaces the previous elements.

simple python code:

d1 = {}
l1=["A1,1","B2,2"]
l2 =[]
for rows in l1:
    print("----- l2 before append")
    print(l2)
    d1["ID"]=rows
    print("-------dict to append ")
    print(d1)
    l2.append(d1)
    print("----- l2 after append")
    print(l2)

print result:

----- l2 before append
[]
-------dict to append 
{'ID': 'A1,1'}
----- l2 after append
[{'ID': 'A1,1'}]
----- l2 before append
[{'ID': 'A1,1'}]
-------dict to append 
{'ID': 'B2,2'}
----- l2 after append
[{'ID': 'B2,2'}, {'ID': 'B2,2'}]

I expected the output of l2 to be [{'ID': 'A1,1'}, {'ID': 'B2,2'}] but I get [{'ID': 'B2,2'}, {'ID': 'B2,2'}]

Selcuk
  • 57,004
  • 12
  • 102
  • 110
Justin
  • 21
  • 2
  • 2
    Nothing puzzling - you re-assigned the key "id" in your dict `d1` during the for loop. – Henry Yik Jul 23 '19 at 02:30
  • 1
    See https://stackoverflow.com/questions/240178/list-of-lists-changes-reflected-across-sublists-unexpectedly – Selcuk Jul 23 '19 at 02:31
  • okay, I got it, so I suppose to create a new list to append instead, else it is referring to the old list and all item in the list are reflected that. – Justin Jul 23 '19 at 02:38
  • @Justin You don't have a new `d1`. Reassigning the key does not reassign the dictionary. Therefore, with each `append`, you have another reference to the same dictionary. If you want a new dictionary, you need to move the `d1 = {}` line under the loop. – Luke Sawczak Jul 23 '19 at 02:40
  • thank you Luke, you solved this.. really appreciated – Justin Jul 23 '19 at 02:44

2 Answers2

2
l1=["A1,1","B2,2"]
l2 =[]
for rows in l1:
    d1 = {}
    #print(id(d1)) 
    # you will find it's a different object each time.
    d1["ID"]=rows
    l2.append(d1)
print(l2)

Or you can do it in this way as below

l1=["A1,1","B2,2"]
l2 = [{"ID":i } for i in l1]
print(l2)

Output is

[{'ID': 'A1,1'}, {'ID': 'B2,2'}]
ComplicatedPhenomenon
  • 4,055
  • 2
  • 18
  • 45
0

A dict can only contain unique keys, so 'ID' is overridden with the new value.

Your list is actually containing the value of the dictd1 if d1 changes, your list will change.

You're using a global dict, and the value changes with the second for loop pass, to to get your intended results, put the d1 = {} inside your for loop instead.

Sam
  • 433
  • 3
  • 8