1

I need help understanding the results I got when I assigned an array to a key of a dictionary, then I modified the key and the array got modified as well:

A = numpy.zeros((2,2))
a = 0
my_dict = {'key1':matrix([]), 'key2':0}

my_list = list()
for i in range(0,2):
    my_dict['key1'] = A[i,:]
    my_dict['key2'] = a
    my_list.append(my_dict)
    my_list[i]['key1'][0] = i+1
    my_list[i]['key2'] = i+1
    
print(my_list)
  [{'key2': 2, 'key1': array([ 2.,  0.])}, {'key2': 2, 'key1': array([ 2.,  0.])}]
print(A)
  [[ 1.  0.]

  [ 2.  0.]]
print(a)
  0

First: why did A get modified and a didn't?

Second: why do I need to write my_dict = {'key1':matrix([]), 'key2':0} at the end of the for loop in order to obtain

  [{'key2': 1, 'key1': array([ 1.,  0.])}, {'key2': 2, 'key1': array([ 2.,  0.])}]

I'm a beginner to Python but this doesn't seem very straightforward to me.

Community
  • 1
  • 1
J. Serra
  • 440
  • 1
  • 4
  • 13
  • 1
    You may find this article helpful: [Facts and myths about Python names and values](http://nedbatchelder.com/text/names.html), which was written by SO veteran Ned Batchelder. – PM 2Ring Jan 12 '18 at 03:14

1 Answers1

1

my_list.append(my_dict) doesn't make a copy of my_dict. All the elements of my_list are references to the same dictionary, which is the value of my_dict. You keep modifying that dict in place when you assign to its keys.

You need to create a new dict every time through the loop.

A = numpy.zeros((2,2))
a = 0

my_list = list()
for i in range(0,2):
    my_dict = {}
    my_dict['key1'] = A[i,:]
    my_dict['key2'] = a
    my_list.append(my_dict)
    my_list[i]['key1'][0] = i+1
    my_list[i]['key2'] = i+1

print(my_list)

why did A get modified and a didn't?

Because assigning to the dictionary property doesn't modify other variables that happen to refer to the same value. The difference with A is that you're modifying the array element my_list[i]['key1'][0] = i+1, not just assigning to the dictionary property my_list[i]['key1'].

In general, when you have multiple references to a mutable object like a list, array, or dictionary, modifying the contents of that object through one of the references changes the object itself, so all the references see the change. But assigning to the reference just changes that one reference.

A simpler example:

a = [1, 2, 3]
b = a
a[0] = 10
b
  [10, 2, 3]
a = [3, 2, 1]
b
  [10, 2, 3]

You see the difference between assigning to a and assigning to a[0]?

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 1
    Thanks Barmar, that solved my Second problem. Is there any method rather than .append() that creats a copy instead? – J. Serra Jan 12 '18 at 05:42
  • 1
    Any guess about my First problem? – J. Serra Jan 12 '18 at 05:43
  • Why do you need a copy? There's nothing from the previous dict that you need to copy, you just want a fresh, empty dict each time. – Barmar Jan 12 '18 at 08:36
  • But you can see https://stackoverflow.com/questions/2465921/how-to-copy-a-dictionary-and-only-edit-the-copy/2465932#2465932 for how to copy a dict. – Barmar Jan 12 '18 at 08:37