views:

97

answers:

4

Im new two python and am trying to grow a dictionary of dictionaries. I have done this in php and perl but python is behaving very differently. Im sure it makes sense to those more familiar with python. Here is my code:

colnames = ['name','dob','id'];
tablehashcopy = {};
tablehashcopy = dict.fromkeys(colnames,{});

tablehashcopy['name']['hi'] = 0;
print(tablehashcopy);

Output:

{'dob': {'hi': 0}, 'name': {'hi': 0}, 'id': {'hi': 0}}

The problem arises from the 2nd to last statement(i put the print in for convenience). I expected to find that one element has been added to the 'name' dictionary with the key 'hi' and the value 0. But this key,value pair has been added to EVERY sub-dictionary. Why?

I have tested this on my ubuntu machine in both python 2.6 and python 3.1 the behaviour is the same.

+3  A: 

The issue is with your fromkeys call. You passed it an empty dictionary, and it used that exact same empty dictionary as the value for all of the keys. Since the exact same dictionary is being used as the value, adding an element to it means you'll see that same element for all the keys' dictionaries.

msalib
+1  A: 

dict.fromkeys(seq, [value]) - value defaults to None if nothing is passed, but since you passed a dict instead, that's what it's using for each key-value pair.

MHarrison
+2  A: 

As msalib says, your problem is that dict.fromkeys makes all the entries in the dictionary point to the same object. Try this instead to create a separate empty dictionary for each key:

tablehashcopy=dict((key,{}) for key in colnames)
Weeble
+1 for a clean alternative to `{}.fromkeys`
tgray
A: 

In your source, only one inner dictionary object is created and used 3 times. So when you modificate it, you will see the change 3 times too, because everything is bound to the same variable.

You can do something like the following to solve the problem. This will create several (key, {}) tuples and use them to generate a dictionary:

colnames = ['name','dob','id']
tablehashcopy = dict((k, {}) for k in colnames)
tablehashcopy['name']['hi'] = 0
print tablehashcopy   # use "print(tablehashcopy)" in Python 3
# output: {'dob': {}, 'name': {'hi': 0}, 'id': {}}

Please also take a look at the formatting (no semicolons) and some statements I've deleted because they were unnecessary.

tux21b