-1

I don't have a huge list so I'd prefer to use the standard library. I'm trying to initialize a dictionary that holds empty values (so I can do math on them later) but when I change one value, others also change.

Example script

l = ['a', 'b', 'c']
d = {'CategoryA': dict.fromkeys(l, dict.fromkeys(l, 0)),
'CategoryB': dict.fromkeys(l, dict.fromkeys(l, 0)),
'CategoryC': dict.fromkeys(l, dict.fromkeys(l, 0))}
d['CategoryA']['a']['c'] += 1

print d['CategoryA']['a']['c']
print d['CategoryA']['b']['c']
print d['CategoryA']['c']['c']

This prints out 1 three times in a row, but I want it to print out 1 and then 0 twice. It seems the final dictionary values are linked.

I also tried creating two identical lists (uglier code), thinking the lists are linked, but that doesn't fix it, and I get the identical printouts with this uglier code:

l1 = ['a', 'b', 'c']
l2 = ['a', 'b', 'c']
d = {'CategoryA': dict.fromkeys(l1, dict.fromkeys(l2, 0)),
'CategoryB': dict.fromkeys(l1, dict.fromkeys(l2, 0)),
'CategoryC': dict.fromkeys(l1, dict.fromkeys(l2, 0))}
d['CategoryA']['a']['c'] += 1
lcb
  • 87
  • 6
  • `.fromkeys` uses the same value for each key. If those values are mutable, this is what happens. Look into a "dictionary comprehension" instead. – jonrsharpe Jan 12 '17 at 21:29
  • 1
    Possible duplicate of [Dictionary creation with fromkeys and mutable objects. A surprise](http://stackoverflow.com/questions/8174723/dictionary-creation-with-fromkeys-and-mutable-objects-a-surprise) – jonrsharpe Jan 12 '17 at 21:30
  • thanks, I read that post but misinterpreted it as a problem with the list.. "you use the same empty list" – lcb Jan 12 '17 at 22:12

1 Answers1

0

So the problem is the 0s (values) not the keys that I was thinking it was. This solves the issue but is there something more readable than this dictionary comprehension?

l = ['a', 'b', 'c']
d = {'CategoryA': dict((i, dict((i, 0) for i in l)) for i in l),
'CategoryB': dict((i, dict((i, 0) for i in l)) for i in l),
'CategoryC': dict((i, dict((i, 0) for i in l)) for i in l)}
d['CategoryA']['a']['c'] += 1

print d['CategoryA']['a']['c']
print d['CategoryA']['b']['c']
print d['CategoryA']['c']['c']

Prints 1 first, then 0 twice as expected.

lcb
  • 87
  • 6