简体   繁体   中英

Nested dictonary in python

I am trying to update the values in the internal dictonary but it is updating in the both, I tried a lot but still facing the same problem. Thanks in advance.

arr = [1,2]
d_int = {'a':False, 'e':False, 'i':False, 'o':False, 'u':False}
d_main ={i : d_int for i in range(len(arr))}
print(d_main)
d_main[0]['a'] = True
d_main[1]['i'] = True
print(d_main)

Result:

{0: {'a': True, 'e': False, 'i': True, 
     'o': False, 'u': False}, 
 1: {'a': True, 'e': False, 'i': True, 
     'o': False, 'u': False}
}

Need something like this:

{0: {'a': True, 'e': False, 'i': False,
     'o': False, 'u': False},
 1: {'a': False, 'e': False, 'i': True,
     'o': False, 'u': False}
}

This is because all values of the d_main refer to the same dict object d_int . Changes to any one of them will reflect across all references. Further read

To avoid the issue, ensure you create a new copy of the dict object during your list comprehension, using copying methods such as .copy .

arr = [1,2]
d_int = {'a':False, 'e':False, 'i':False, 'o':False, 'u':False}
d_main ={i : d_int.copy() for i in range(len(arr))} #modified.
print(d_main)
d_main[0]['a'] = True
d_main[1]['i'] = True
print(d_main)
#Output:
{0: {'a': True, 'e': False, 'i': False, 'o': False, 'u': False}, 1: {'a': False, 'e': False, 'i': True, 'o': False, 'u': False}}

Short workaround: Change d_int to d_int.copy() and you'll have your output. You are referencing the same object. Look at the difference in the id in these two cases:

Case 1 (your attempt)

arr = [1,2]
d_int = {'a':False, 'e':False, 'i':False, 'o':False, 'u':False}
d_main ={i : d_int for i in range(len(arr))}
print(list(map(id,d_main.values())))

Returns:

[140545244867248, 140545244867248] # <-- they are the same

Case 2 (possible work-around)

arr = [1,2]
d_int = {'a':False, 'e':False, 'i':False, 'o':False, 'u':False}
d_main ={i : d_int.copy() for i in range(len(arr))} # <-- .copy() added
print(list(map(id,d_main.values())))

Returns:

[140545244796464, 140545244798480]

If you are new without any programming experience in any programming language, For understanding why the problem happen, you'd better to know what is pointer in C programming language firstly.


copy.deepcopy is the best. dict.copy have same trouble in deep nested dict. as follows.

a = {"1": {"2": 2, "3": 3}, "4":4}

c = {1:a.copy()}
b = {1:a.copy()}

c[1]['1']['2'] = 5
c[1]['4'] = 40

print(c)
# {1: {'1': {'3': 3, '2': 5}, '4': 40}}
print(b)
# {1: {'1': {'3': 3, '2': 5}, '4': 4}}

But copy.deepcopy is work well with deep nested dict.

from copy import deepcopy

a = {"1": {"2": 2, "3": 3}, "4":4}

c = {1: deepcopy(a)}
b = {1: deepcopy(a)}

c[1]['1']['2'] = 5
c[1]['4'] = 40

print(c)
# {1: {'1': {'2': 5, '3': 3}, '4': 40}}

print(b)
# {1: {'1': {'2': 2, '3': 3}, '4': 4}}

Actually, this problem is not only happen to nested dict, other types as well, likes nested list, class with dict property and so on, and copy.deepcopy is work well.

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