0

Basically I just want to change nested dictionaries but in my code I change multiple sublevel dictionaries at once.

So I have a nested dictionary which looks this way

d1 = {'a': {0: [1,2], 1: [1,2]}, 'b': {0: [1,2], 1: [1,2]}}

Then I want to add an entry

d1['a'][2] = [2,2]

And then I get what I want

{'a': {0: [1, 2], 1: [1, 2], 2: [2, 2]}, 'b': {0: [1, 2], 1: [1, 2]}}

But when I want to create my dictionary like this (and I need it that way, because my dict has to have different lengths and so on)

d2 = dict.fromkeys(['a','b'], dict.fromkeys([0,1], [1,2]))

I will get

{'a': {0: [1, 2], 1: [1, 2], 2: [2, 2]}, 'b': {0: [1, 2], 1: [1, 2], 2: [2, 2]}}

so it will add the new dictionary entry to both lower level dictionaries. Why does it do this and how can I prevent this? I tried now a lot of stuff but I cant manage to solve this... Maybe you can help?

  • Does this answer your question? [Initailizing nested dict with .fromkeys](https://stackoverflow.com/questions/45574832/initailizing-nested-dict-with-fromkeys) – systemexit Nov 15 '22 at 00:38

2 Answers2

0

You can check answers here:

Unwanted behaviour from dict.fromkeys

If dict().fromkeys() all point to the same object, what purpose does the default value argument serve?

In particular, if you try:

dict.fromkeys(['a','b'], object())

you will see that the adresses are the same:

{'a': <object at 0x2fa88dfebe0>, 'b': <object at 0x2fa88dfebe0>}
Thomas
  • 26
  • 2
-1

When you run dict.fromkeys(keys, default) it creates a dictionary with the keys you provided and gives all of them the same default value you provided. Your problem is that the default value you provided is itself a dictionary which is mutable. Because it is mutable it is stored as a reference to one object. When you reference it in two places they are both references to the same object.

You will need to run dict.copy() to create a separate copy.

A way of generating a dict that will work for your case is.

d1 = dict.fromkeys([0,1], [1,2])
d2 = {key:d1.copy() for key in ["a", "b"]}

But keep in mind you'll now have the same issue one level lower in d1 as the [1,2] lists are all the same list.

  • "Because it is mutable it is stored as a reference to one object." - this has nothing to do with `default` being mutable or not. `dict.fromkeys` always uses the *same* object as value for all keys. The only thing is that you can't have any problem with non mutable objects, as you can't mutate a value, but only replace the value object for a given key by a different object. – Thierry Lathuille Nov 15 '22 at 01:01