简体   繁体   中英

Why doesn't deepcopy work on a python dictionary?

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM