1

I've many lists holding many dictionaries inside a list. I simply assign to one dictionary in one of the lists in the outer list. But it leads to assignment to all dictionaries in all lists in the outer list.

The code:

CL=3*[0]
DL=4*[0]
di= {
     'A':[],
     'B':[],
     'C':CL,
     'D':DL
    }
R=[[],[]]
R[0].append(di)
R[1].append(di)

def func(dd):
    dd[0][0]['A'].append("BANANA")
    dd[0][0]['B'].append("ELEPHANT")
    dd[0][0]['C'][0]='BLUE'
    dd[0][0]['D'][3]='ROCK'
    dd[0][0]['D'][2]=1111

print(R[0])
print(R[1])

print("\n")

func(R)

print(R[0])
print(R[1])

The output:

[{'A': [], 'C': [0, 0, 0], 'B': [], 'D': [0, 0, 0, 0]}]                                                                                                    
[{'A': [], 'C': [0, 0, 0], 'B': [], 'D': [0, 0, 0, 0]}]                                                                                                    


[{'A': ['BANANA'], 'C': ['BLUE', 0, 0], 'B': ['ELEPHANT'], 'D': [0, 0, 1111, 'ROCK']}]                                                                     
[{'A': ['BANANA'], 'C': ['BLUE', 0, 0], 'B': ['ELEPHANT'], 'D': [0, 0, 1111, 'ROCK']}]

As you can see, even though I assigned values to the dictionary in the first list in the outer list (func() operates only on dd[0]..), both the lists got assigned.

Is there any mistake in my indexing anywhere? Why does this happen?

halfer
  • 19,824
  • 17
  • 99
  • 186
nPab
  • 19
  • 3
  • 1
    R[0] and R[1] hold the same dictionary, not two separate copies of the initial dictionary. see http://lucumr.pocoo.org/2011/7/9/python-and-pola/#pass-by-what-exactly – TheoretiCAL Jul 27 '17 at 17:28
  • 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 Jul 27 '17 at 17:36

2 Answers2

3
di= {
     'A':[],
     'B':[],
     'C':CL,
     'D':DL
    }
R=[[],[]]
R[0].append(di)
R[1].append(di)

di is di is di. Each use of di doesn't create separate copies. There is only one di and so R[0][0] is R[1][[0] and all changes appear in the same dict.

To fix your code:

from copy import deepcopy
R[0].append(deepcopy(di))
R[1].append(deepcopy(di))
Alex Hall
  • 34,833
  • 5
  • 57
  • 89
2

The code

R[0].append(di)
R[1].append(di)

adds di to R by reference. That means that both R[0] and R[1] refer to the same underlying object. Thus, changing one changes the underlying object and therefore changes both.

Sumner Evans
  • 8,951
  • 5
  • 30
  • 47