J.C Guzman
J.C Guzman

Reputation: 1334

Cannot update nested dictionary properly

I am working with Python 3.8.5

I have created some objects like this:

class TestClass:
    def __init__(self, key, value):
        self.key=key
        self.value=value

test1 = TestClass(1, 'a')
test2 = TestClass(2, 'b')
test3 = TestClass(3, 'c')

test_list = [test1, test2, test3]

I want to create a dictionary to keep track the modifications in this objects:

object_mapper = {
    'ClassNotRelevant': None,
    'TestClass': None,
    'ClassNotRelevant2': None,
}

test_dict = {test.key: object_mapper for test in test_list}

#output
{1: {'ClassNotRelevant': None, 'TestClass': None, 'ClassNotRelevant2': None},
 2: {'ClassNotRelevant': None, 'TestClass': None, 'ClassNotRelevant2': None},
 3: {'ClassNotRelevant': None, 'TestClass': None, 'ClassNotRelevant2': None}}

Now, I want to set the value property for each class in the dictionary, like this:

#expected dictionary
#output
{1: {'ClassNotRelevant': None, 'TestClass': 'a', 'ClassNotRelevant2': None},
 2: {'ClassNotRelevant': None, 'TestClass':'b', 'ClassNotRelevant2': None},
 3: {'ClassNotRelevant': None, 'TestClass':'c', 'ClassNotRelevant2': None}}

I am trying to do the following:

for test in test_list:
    test_dict[test.key]['TestClass']= test.value

but the output is:

{1: {'ClassNotRelevant': None, 'TestClass': 'c', 'ClassNotRelevant2': None},
 2: {'ClassNotRelevant': None, 'TestClass': 'c', 'ClassNotRelevant2': None},
 3: {'ClassNotRelevant': None, 'TestClass': 'c', 'ClassNotRelevant2': None}}

I have tried the different solutions found in: Updating nested dictionaries when data has existing key

But anything worked, what I am doing wrong?

Upvotes: 1

Views: 63

Answers (2)

user15801675
user15801675

Reputation:

Here is the code which will solve the question. It will create a copy of the object_mapper for each iteration.

test_dict = {test.key: object_mapper.copy() for test in test_list}
for test in test_list:
    test_dict[test.key]['TestClass']=test.value
print(test_dict)

Upvotes: 0

Prakhar
Prakhar

Reputation: 1014

The problem lies here

When you do this

test_dict = {test.key: object_mapper for test in test_list}

Output is

{1: {'ClassNotRelevant': None, 'TestClass': None, 'ClassNotRelevant2': None},
 2: {'ClassNotRelevant': None, 'TestClass': None, 'ClassNotRelevant2': None},
 3: {'ClassNotRelevant': None, 'TestClass': None, 'ClassNotRelevant2': None}}

This {'ClassNotRelevant': None, 'TestClass': None, 'ClassNotRelevant2': None} is the same object (object_mapper) corresponding to key `1 2 3'

So when you update using this :

for test in test_list:
    test_dict[test.key]['TestClass']= test.value

This updates the object_mapper object so,

After 1st iteration:

{1: {'ClassNotRelevant': None, 'TestClass': 'a', 'ClassNotRelevant2': None},
 2: {'ClassNotRelevant': None, 'TestClass': 'a', 'ClassNotRelevant2': None},
 3: {'ClassNotRelevant': None, 'TestClass': 'a', 'ClassNotRelevant2': None}}

2nd Iteration

{1: {'ClassNotRelevant': None, 'TestClass': 'b', 'ClassNotRelevant2': None},
 2: {'ClassNotRelevant': None, 'TestClass': 'b', 'ClassNotRelevant2': None},
 3: {'ClassNotRelevant': None, 'TestClass': 'b', 'ClassNotRelevant2': None}}

3rd Iteration

{1: {'ClassNotRelevant': None, 'TestClass': 'c', 'ClassNotRelevant2': None},
 2: {'ClassNotRelevant': None, 'TestClass': 'c', 'ClassNotRelevant2': None},
 3: {'ClassNotRelevant': None, 'TestClass': 'c', 'ClassNotRelevant2': None}}

So Instead of

test_dict = {test.key: object_mapper for test in test_list}

use

test_dict = {test.key: object_mapper.copy() for test in test_list}

which will create shallow_copy of object_mapper object for each entry, instead of putting object_mapper object itself there.

Upvotes: 2

Related Questions