0

I have a question about some python dictionary behavior i haven't seen yet. (i am using python3.6)

I have a dictionary first_dict containing two keys "kk" and "aa", both linked to a list. Then i make a new dict namly second_dict. Now comes the strange thing, whenever i make a variable like fractions and edit this value, it automatically updates my dictionary. So i assume python automatically makes a connection between dictionary derived variables.

def main():

    first_dict = {"kk": [0.0, 1.0], "aa": [0.5, 1.0]}
    second_dict = first_dict
    fractions = second_dict["kk"]

    fractions.pop(0) #del fractions[0] gives same result
    print(first_dict)  #{'kk': [1.0], 'aa': [0.5, 1.0]}
    print(second_dict) #{'kk': [1.0], 'aa': [0.5, 1.0]}

if __name__ == "__main__":
    main()

My question is can i remove these connections, i found a solution to remove the connection between fractions and my second_dict by using:

fractions = list(second_dict["kk"])

however i could not find a solution to remove the connection between first_dict and second_dict. So i want to change second_dict and leave the first_dict unchanged.

candah
  • 124
  • 5
  • The keyword for this behavior is "mutable", see e.g. https://stackoverflow.com/questions/24292174/are-python-lists-mutable . Your `second_dict` is indeed not a second dict, but a second name for the same dict. – syntonym Mar 06 '18 at 08:50
  • the first solution in the "duplicate" post do not solve my problem. so dict2 = dict(dict1) and dict2 = dict1.copy() do not work. How come? – candah Mar 06 '18 at 09:29
  • @candah: because `dict(dictionary)` and `dictionary.copy()` create a *shallow* copy, so the contained list objects in the values are still shared. – Martijn Pieters Mar 06 '18 at 10:13
  • @candah: You really want to read [this article on Python names and references](https://nedbatchelder.com/text/names.html), to understand what is going on. – Martijn Pieters Mar 06 '18 at 10:14

2 Answers2

4

What you are really trying to say is that you want first_dict and second_dict to point to different objects, instead of the same one

This could be done by replacing second_dict = first_dict

With

from copy import deepcopy
second_dict = deep_copy(first_dict)
omu_negru
  • 4,642
  • 4
  • 27
  • 38
2

It has nothing to do with dictionaries specifically.

First off, you never made a new dictionary (shallow copy). To do that:

new_dictionary = dict(old_dictionary)

Secondly, lists are mutable. When you shallow-copy you have the same references for the key values, so mutating an object manifests anywhere it is referenced. Maybe you want to deepcopy:

from copy import deepcopy
new_dictionary = deepcopy(old_dictionary)

A better way is using immutable objects whenever possible (the equivalent for a list is usually a tuple in python).

Reut Sharabani
  • 30,449
  • 6
  • 70
  • 88