RXP
RXP

Reputation: 677

Error Appending list elements to dictionary in Python

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

Answers (4)

CodeMonkey
CodeMonkey

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

j1-lee
j1-lee

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

schilli
schilli

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

Connor
Connor

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

Related Questions