Increment items in nested python dict

songololo

I have a nested Python Dict and I am trying to take values from a list and then iterate them into a Dict's values as such:

for row in rows:
  Dict[A][AA][AAA] += 1

However, when I print my dict, it appears to be adding all of the increments to all of the Dict entries. By which I mean that instead of this:

{KeyA:{KeyAA:{KeyAAA:5}}}
{KeyB:{KeyBB:{KeyBBB:10}}}

I am getting this:

{KeyA:{KeyAA:{KeyAAA:15}}}
{KeyB:{KeyBB:{KeyBBB:15}}}

I'm a bit stumped.

EDIT: This is how the Dicts were created: I first skim through a long table that contains a type classification. While I'm doing that, I create a new entry into the main Dict. At the same time, I'm collecting all of the unique classifications into a subDict so that I can add this to the main Dict later on:

Dict = {}
subDict = {}
for row in skimRows:
  Dict[row[0]] = {"Type":row[1],"Assoc":{}} # Save each ID and origin Type to Dict
  if item not in subDict: # Check to see if unique item already exists in subDict
    subDict[item] = 0

Here is evidently where I was going wrong. I was then taking the subDict and plunking this into the main Dict, not realising the inserted subDict was retaining its relationship to the original subDict object:

for key in Dict: # After initial iteration and Type collection, add new subDict to each Dict key
  Dict[key]["Assoc"] = subDict

SOLUTION: Per the correct answer below, I fixed it by adding .copy()

for key in Dict: # After initial iteration and Type collection, add new subDict to each Dict key
  Dict[key]["Assoc"] = subDict.copy()
Martijn Pieters

Your innermost dictionaries are shared, not unique objects:

>>> somedict = {}
>>> somedict['foo'] = {'bar': 0}
>>> somedict['spam'] = somedict['foo']
>>> somedict['foo']['bar'] += 1
>>> somedict['spam']
{'bar': 1}
>>> somedict['foo'] is somedict['spam']
True

The two keys foo and spam both are referring to the same object here, one dictionary object holding a key bar.

You should not reuse your dictionaries like this. Either create a new empty dictiorary:

somedict['spam'] = {'bar': 0}

or create a (shallow) copy:

somedict['spam'] = somedict['foo'].copy()

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related