dict.fromkeys all point to same list

dict from keys and values python
dict.fromkeys python 3
dict fromkeys set
python new dictionary from keys
python dictionary
python dict from keys empty list
type object 'dict' has no attribute 'fromkeys'
sorted list dict fromkeys score_list

This was causing me a bit of grief...

I created a dictionary from a list

l = ['a','b','c']
d = dict.fromkeys(l, [0,0]) # initializing dictionary with [0,0] as values

d['a'] is d['b'] # returns True

How can I make each value of the dictionary a seperate list? Is this possible without iterating over all keys and setting them equal to a list? I'd like to modify one list without changing all the others.

You could use a dict comprehension:

>>> keys = ['a','b','c']
>>> value = [0, 0]
>>> {key: list(value) for key in keys}
    {'a': [0, 0], 'b': [0, 0], 'c': [0, 0]}

Python Dictionary fromkeys(), The fromkeys() method creates a new dictionary from the given sequence of elements with a value Example 3: Create a dictionary from mutable object list. script. This is because, each element is assigned a reference to the same object (points to the same object in the memory). Parewa Labs Pvt. Ltd. All rights reserved. The default behavior of fromkeys() is to assign None to the value. Indeed, all of the values are the same (and the only!) None. Now, let's iterate, in one of a myriad number of ways, through the dict and change the value.

This answer is here to explain this behavior to anyone flummoxed by the results they get of trying to instantiate a dict with fromkeys() with a mutable default value in that dict.

Consider:

#Python 3.4.3 (default, Nov 17 2016, 01:08:31) 

# start by validating that different variables pointing to an
# empty mutable are indeed different references.
>>> l1 = []
>>> l2 = []
>>> id(l1)
140150323815176
>>> id(l2)
140150324024968

so any change to l1 will not affect l2 and vice versa. this would be true for any mutable so far, including a dict.

# create a new dict from an iterable of keys
>>> dict1 = dict.fromkeys(['a', 'b', 'c'], [])
>>> dict1
{'c': [], 'b': [], 'a': []}

this can be a handy function. here we are assigning to each key a default value which also happens to be an empty list.

# the dict has its own id.
>>> id(dict1)
140150327601160

# but look at the ids of the values.
>>> id(dict1['a'])
140150323816328
>>> id(dict1['b'])
140150323816328
>>> id(dict1['c'])
140150323816328

Indeed they are all using the same ref! A change to one is a change to all, since they are in fact the same object!

>>> dict1['a'].append('apples')
>>> dict1
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']}
>>> id(dict1['a'])
>>> 140150323816328
>>> id(dict1['b'])
140150323816328
>>> id(dict1['c'])
140150323816328

for many, this was not what was intended!

Now let's try it with making an explicit copy of the list being used as a the default value.

>>> empty_list = []
>>> id(empty_list)
140150324169864

and now create a dict with a copy of empty_list.

>>> dict2 = dict.fromkeys(['a', 'b', 'c'], empty_list[:])
>>> id(dict2)
140150323831432
>>> id(dict2['a'])
140150327184328
>>> id(dict2['b'])
140150327184328
>>> id(dict2['c'])
140150327184328
>>> dict2['a'].append('apples')
>>> dict2
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']}

Still no joy! I hear someone shout, it's because I used an empty list!

>>> not_empty_list = [0]
>>> dict3 = dict.fromkeys(['a', 'b', 'c'], not_empty_list[:])
>>> dict3
{'c': [0], 'b': [0], 'a': [0]}
>>> dict3['a'].append('apples')
>>> dict3
{'c': [0, 'apples'], 'b': [0, 'apples'], 'a': [0, 'apples']}

The default behavior of fromkeys() is to assign None to the value.

>>> dict4 = dict.fromkeys(['a', 'b', 'c'])
>>> dict4
{'c': None, 'b': None, 'a': None}
>>> id(dict4['a'])
9901984
>>> id(dict4['b'])
9901984
>>> id(dict4['c'])
9901984

Indeed, all of the values are the same (and the only!) None. Now, let's iterate, in one of a myriad number of ways, through the dict and change the value.

>>> for k, _ in dict4.items():
...    dict4[k] = []

>>> dict4
{'c': [], 'b': [], 'a': []}

Hmm. Looks the same as before!

>>> id(dict4['a'])
140150318876488
>>> id(dict4['b'])
140150324122824
>>> id(dict4['c'])
140150294277576
>>> dict4['a'].append('apples')
>>> dict4
>>> {'c': [], 'b': [], 'a': ['apples']}

But they are indeed different []s, which was in this case the intended result.

Python dictionary fromkeys() Method, seq − This is the list of values which would be used for dictionary keys preparation. value − This is optional, if provided then value would be set to this value. Return  Python Dictionary fromkeys() The fromkeys() method creates a new dictionary from the given sequence of elements with a value provided by the user.

You can use this:

l = ['a', 'b', 'c']
d = dict((k, [0, 0]) for k in l)

odd dictionary behavior with dict.fromkeys() : learnpython, https://stackoverflow.com/questions/15516413/dict-fromkeys-all-point-to-same-list​. So, you can't create separate lists with dict.fromkeys(). Instead, use a  dict.fromkeys(seq[, value]) Parameters. seq − This is the list of values which would be used for dictionary keys preparation. value − This is optional, if provided then value would be set to this value. Return Value. This method returns the list. Example. The following example shows the usage of fromkeys() method.

l = ['a','b','c']
d = dict((i, [0, 0]) for i in l)

Python Dictionary, Returns : A dictionary with keys mapped to None if no value is provided, else to of dictionary, i.e if we append value in original list, the append takes place in all a new list as key values, that does not point to original list as values of keys. dict.fromKeys() accepts a list and default value. It returns a dictionary with items in list as keys. All dictionary items will have same value, that was passed in fromkeys(). If no default value was passed in fromKeys() then default value for keys in dictionary will be None.

Python Dictionary FromKeys Example, Python Dictionary fromKeys() is an inbuilt function that creates a new In the final output, the values will be the same for all the keys in the original list, the append takes place in all the values of keys. It is because each element is assigned a reference to the same object (points to the same object in the  dict.fromkeys(seq[, value])) Parameters. seq − This is the list of values which would be used for dictionary keys preparation. value − This is optional, if provided then value would be set to this value. Return Value. This method returns the list. Example. The following example shows the usage of fromkeys() method.

Python Dictionary fromkeys() Method, The fromkeys() method creates a new dictionary with default value for all dictionaries from keys lists, in much the same way as the fromkeys() method. Syntax¶. dict.fromkeys(iterable[, value]) iterable Required. Any iterable. value Optional. Default value for the keys. Default value is None.

fromkeys, Returns a new dictionary with keys from a supplied iterable and values all set to specified value. Syntax¶. dict. fromkeys(iterable[, value]). iterable: Required. Any​  As everyone is probably aware by now, in Python 3 dict.keys(), dict.values() and dict.items() will all return iterable views instead of lists. The standard way being suggested to overcome the difference, when the original behavior was actually intended, is to simply use list(dict.keys()). This should be usually fine, but not in all cases.

Comments
  • Possible duplicate of How do I initialize a dictionary of empty lists in Python?
  • list(value) is the same thing as value[:] here?
  • @Droogans: Yep. I just find the empty slice notation ugly.
  • value[:] isn't that ugly (unless you share Alex Martelli's aesthetic sense :) ), and it's less typing. In recent versions of Python there's now a list.copy method. In terms of performance, slicing is fastest for small lists (upto 50 or 60 items), but for larger lists list(value) is actually a little faster. value.copy() seems to have similar performance to list(value). All 3 techniques dramatically slow down for large lists: on my old 32 bit machine that happens around 32k, YMMV depending on your CPU's word size and cache sizes.
  • So we have to iterate?