1

I found some "mystery" problem when I'm trying filling list in "for in" loop.

Here is example:

>>> params = [1,2,3,4,5]
>>> el = {'param':0}
>>> el
{'param': 0}
>>> list = []
>>> for param in params:
...     el['param'] = param
...     list.append(el)
... 
>>> print(list)
[{'param': 5}, {'param': 5}, {'param': 5}, {'param': 5}, {'param': 5}]
>>> 

But I think result should be

>>> print(list)
[{'param': 1}, {'param': 2}, {'param': 3}, {'param': 4}, {'param': 5}]
>>> 

How to resolve this problem? And why real result isn't similar with result in my mind?

dsh
  • 12,037
  • 3
  • 33
  • 51
gostin
  • 31
  • 2
  • Your result is correct. `el` is a dictionary that gets uodated all the time on the value param. You are also storing a **reference** to this dictionary on the the list, hence the result – Yannis P. Feb 01 '16 at 21:11
  • Read [this question](http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference). – Zenadix Feb 01 '16 at 21:17

5 Answers5

3

Every element in your list contains a reference to the same dict. That is why you are seeing the same number in every element. Perhaps you want to do:

params = [1,2,3,4,5]

a = []
for param in params:
    el = {'param': param}
    a.append(el)

Also, be careful of shadowing builtins such as list with your variable names.

YXD
  • 31,741
  • 15
  • 75
  • 115
  • Thanks! But if haven't chance to create new el object in each iteration? Can I say python that I want value not reference? – gostin Feb 01 '16 at 21:15
  • No. Python only works with references. If you want to copy the value, you must do so explicitly (either creating a new object, or using the `copy` method) – spectras Feb 01 '16 at 21:25
2

el refers to the same dictionary throughout, and list.append(el) adds a reference to that dictionary, not a copy of its current value, to the list. You don't have a list of 5 different dictionaries, but a list of 5 references to one dictionary.

To see what is happening in closer detail, print list and el each time through the loop. You'll see a growing list that always refers to the current value of el.

chepner
  • 497,756
  • 71
  • 530
  • 681
1

The problem is that you are using the same dictionary for each entry in your list. To fix this problem, add el = {} above el['param'] = param in your for loop.

zondo
  • 19,901
  • 8
  • 44
  • 83
1

You modify the same dict in every iteration and add it to the list. You'll get the other result when adding copies of this dict to the list.

Just call list.append(dict(el)) instead.

tynn
  • 38,113
  • 8
  • 108
  • 143
0

You have one dict object that you are modifying. You add a reference to that one dict to your list multiple times. So your list contains 5 references to the same dict object.

dsh
  • 12,037
  • 3
  • 33
  • 51