Reputation: 677
I have a weird problem when trying to append a list of elements to a dictionary. I am not sure what I am doing wrong. Any help is very much appreciated.
here is what I have:
keys = ['a', 'b', 'c']
d = dict.fromkeys(keys, [])
d['a'].append(10)
d['a'].append(11)
d['b'].append(30)
print(d)
the output I am getting is:
{'a': [10, 11, 30], 'b': [10, 11, 30], 'c': [10, 11, 30]}
I would expect:
{'a': [10, 11], 'b': [30], 'c': None}
Thank you
Upvotes: 3
Views: 1920
Reputation: 23738
The same list object is being referenced by each dictionary key. fromkeys()
creates a new dictionary with keys and values are set to the specified value, which in this case is a single list object that is shared among the dict key items.
Try this to assign a new list to each key value of the dictionary:
keys = ['a', 'b', 'c']
d = {key: [] for key in keys}
d['a'].append(10)
d['a'].append(11)
d['b'].append(30)
print(d)
Output:
{'a': [10, 11], 'b': [30], 'c': []}
Upvotes: 3
Reputation: 13929
You are providing an empty list, and fromkeys()
uses this particular object for all the keys, so that their corresponding values refer to the same object. When you do d['a'].append(10)
, it appends 10
to this single object, which all the dict items share, thus resulting in what you are getting now.
Python document mentions this exact situation:
fromkeys() is a class method that returns a new dictionary. value defaults to None. All of the values refer to just a single instance, so it generally doesn’t make sense for value to be a mutable object such as an empty list. To get distinct values, use a dict comprehension instead.
— https://docs.python.org/3/library/stdtypes.html#mapping-types-dict
Following the suggetion in the python doc, you can do d = {k: [] for k in keys}
instead.
Upvotes: 4
Reputation: 1838
This is actually an interesting question. Apparently, fromkeys
assigns the same list object to all dict keys. You can see this by applying the id()
function call to the values of the dict. This function gives you the memory address of the variable. In this case, you'll get the same address for alle keys. Hence, by appending the list of one key's list, the other lists are also appended, because it's the same memory address aka the same list.
keys = ['a', 'b', 'c']
d = dict.fromkeys(keys, [])
d['a'].append(10)
d['a'].append(11)
d['b'].append(30)
print(id(d['a']))
print(id(d['b']))
print(id(d['c']))
print(d)
# Output
4418025728
4418025728
4418025728
{'a': [10, 11, 30], 'b': [10, 11, 30], 'c': [10, 11, 30]}
Upvotes: 3
Reputation: 297
Does this solve your problem?
d = {'a': [], 'b': [], 'c': []}
d['a'].append(10)
d['a'].append(11)
d['b'].append(30)
print(d)
Upvotes: 1