Wednesday, May 7, 2014

Python dict.fromkeys() magic

I just got some magic from python and what to share with the world.
Imagine we have some python code:
keys = ("T1", "T2", "T3")
td = dict.fromkeys(keys, [])
print td
{'T2': [], 'T3': [], 'T1': []}

Ok. Now lets try to populate new dictionary with some data:

for i in range(0,5):
 for v in td.itervalues():
  v.append(1)
print td

I think you are expecting to get something like:
{'T2': [1, 1, 1, 1, 1], 'T3': [1, 1, 1, 1, 1], 'T1': [1, 1, 1, 1, 1]}

But Nope! You will see this one:
{'T2': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 'T3': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 'T1': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

The magic comes from fromkeys() function. It seems the function links all dictionary keys to one list object. Lets check it:

for k in td.itervalues():
 print id(k)
140567008377312
140567008377312
140567008377312

Yes, it's true! So be carefully with fromkeys() or use something like:
td = dict((k, []) for k in keys)

P.S.
Thanks to Alexey Gusev for this case.
And yes, when we have understood the problem I easily found this discussion on stackoverflow.