0

How to achieve deepcopy in dictionaries?

My original code :

li1 = ['Column_6', 'Column_11']
delimiters = ['a','b','c','d']
inner_dict = dict.fromkeys(delimiters,[0,0])
delim_dict = dict.fromkeys(li1 ,None)
for k,v in delim_dict.items():
    delim_dict[k] = copy.deepcopy(inner_dict) 

print (delim_dict) gives

{'Column_6': {'a': [0, 0], 'b': [0, 0], 'c': [0, 0], 'd': [0, 0]},
 'Column_11': {'a': [0, 0], 'b': [0, 0], 'c': [0, 0], 'd': [0, 0]}}
delim_dict['Column_6']['a'][0]=5
print (delim_dict)

gives

{'Column_6': {'a': [5, 0], 'b': [5, 0], 'c': [5, 0], 'd': [5, 0]},
 'Column_11': {'a': [0, 0], 'b': [0, 0], 'c': [0, 0], 'd': [0, 0]}}

Why keys b,c,d are updated with [5, 0] in spite of deepcopy?

I am able to achieve result with the Modified code :

li1 = ['Column_6', 'Column_11']
delimiters = ['a','b','c','d']
#inner_dict = dict.fromkeys(delimiters,[0,0])
delim_dict = dict.fromkeys(li1 ,None)
for k,v in delim_dict.items():
    delim_dict[k] = {}
    for delim in delimiters:
        delim_dict[k][delim]=[0,0]

But, how can i achieve the same result with deep copy or is there any other efficient way?

Note: I tried following this link: Deep copy of a dict in python No luck.

usr_lal123
  • 650
  • 12
  • 28

2 Answers2

1

You're using the same list object as all inner_dict values, and deepcopy respects that and keeps it that way. Which you clearly don't want. So don't do that in the first place. Do inner_dict = {d: [0, 0] for d in delimiters} instead.

As the fromkeys documentation says:

All of the values refer to just a single instance, so it generally doesn’t make sense for value to be a mutable object such as an empty list. To get distinct values, use a dict comprehension instead.

superb rain
  • 5,300
  • 2
  • 11
  • 25
0

You can try something like:

li1 = ['Column_6', 'Column_11']
delimiters = ['a','b','c','d']
inner_dict = dict.fromkeys(delimiters,[0,0])
delim_dict = dict.fromkeys(li1 ,None)
for k,v in delim_dict.items():
    delim_dict[k] = {key: value[:] for key, value in inner_dict.items()}

print (delim_dict)

delim_dict['Column_6']['a'][0]=5
print (delim_dict)

with [:] splicing and no use of the copy module

Andi Domi
  • 731
  • 2
  • 19
  • 48