Anna-Lischen
Anna-Lischen

Reputation: 878

Why nested dictionary is filled wrongly?

I have an empty nested dictionary of such a design:

{'PEAR': {'GREEN': [], 'YELLOW': [], 'RED': []}, 'APPLE': {'GREEN': [], 'YELLOW': [], 'RED': []}, 'COURGETTE': {'GREEN': [], 'YELLOW': [], 'RED': []}}

And here is my code:

dictSub = {'RED' : [], 'GREEN' : [], 'YELLOW' : []}
arrMainCodes = ['APPLE', 'PEAR', 'COURGETTE']
dictAll = {}
numbers = {1 : [1, 2, 3], 2 : [4, 56, 7], 3 : [8, 2, 10]}

for item in arrMainCodes:
    dictAll[item] = dictSub
print(dictAll)
dictAll['PEAR']['RED'].append(478)
dictAll['PEAR']['RED'].append(47)
dictAll['PEAR']['RED'].append(8)
print(dictAll)
ITEM = [478, 7, 56]
for i in ITEM:
    if i not in dictAll['PEAR']['RED']:
        dictAll['PEAR']['RED'].append(i)
print(dictAll)

I am trying to fill it in such a manner, that only sublist 'RED' of key 'PEAR' will be filled. However, my result looks like that:

{'PEAR': {'GREEN': [], 'YELLOW': [], 'RED': [478, 47, 8, 7, 56]}, 'APPLE': {'GREEN': [], 'YELLOW': [], 'RED': [478, 47, 8, 7, 56]}, 'COURGETTE': {'GREEN': [], 'YELLOW': [], 'RED': [478, 47, 8, 7, 56]}}

As you can see everything 'RED' is filled, while I want only red pear to be filled.

What am I doing wrong? How can this be solved?

Upvotes: 0

Views: 46

Answers (2)

Mark Reed
Mark Reed

Reputation: 95252

They are all references to a single dictionary. Your first four statements are the only ones that actually create new dictionary objects; your for loop just creates additional names that all refer to the same one.

You can solve that by replacing this assignment:

dictAll[item] = dictSub

with this:

dictAll[item] = dictSub.copy()

That will get you separate dictionaries, but each one will still have references to the same lists. To make sure everything is a fresh copy, use deepcopy() instead:

dictAll[item] = dictSub.deepcopy()

Upvotes: 2

sudheesh shetty
sudheesh shetty

Reputation: 368

The problem is python. Python never copies any objects. SO whenever you assign an dict or array keeps a reference and whenever you change one, changes will reflect in all references. You can do this.

arrMainCodes = ['APPLE', 'PEAR', 'COURGETTE']
dictAll = {}
numbers = {1 : [1, 2, 3], 2 : [4, 56, 7], 3 : [8, 2, 10]}

for item in arrMainCodes:
    dictAll[item]={'RED' : [], 'GREEN' : [], 'YELLOW' : []}
print(dictAll)
dictAll['PEAR']['RED'].append(478)
dictAll['PEAR']['RED'].append(47)
dictAll['PEAR']['RED'].append(8)
print(dictAll)
ITEM = [478, 7, 56]
for i in ITEM:
    if i not in dictAll['PEAR']['RED']:
        dictAll['PEAR']['RED'].append(i)
print(dictAll)

This will create separate dict with new lists every time.

Upvotes: 0

Related Questions