0

Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)]

my_list = ["a","b","c"]

dict_one = {key:[] for key in my_list}
print(dict_one)
{'a': [], 'b': [], 'c': []}

dict_two = dict.fromkeys(my_list, [])
print(dict_two)
{'a': [], 'b': [], 'c': []}

dict_one['a'].append('some_data')
dict_two['a'].append('some_data')

print(dict_one)
{'a': ['some_data'], 'b': [], 'c': []}

print(dict_two)
{'a': ['some_data'], 'b': ['some_data'], 'c': ['some_data']}

I excpected the same result for dict_one and dict_two. Could anyone please explain the difference ?

steve
  • 17
  • 1
  • Also: [How do I initialize a dictionary of empty lists in Python?](https://stackoverflow.com/q/11509721/7851470) – Georgy Jan 22 '20 at 16:26
  • Also: [Append value to one list in dictionary appends value to all lists in dictionary](https://stackoverflow.com/q/23397153/7851470) – Georgy Jan 22 '20 at 16:28

1 Answers1

7

It's a variation on “Least Astonishment” and the Mutable Default Argument .

fromkeys does not create a new empty list for each value it adds to the dict it is building; it uses the same (mutable) value you provided as the second argument.


As an aside, it would be nice if there was a way to provide a factory to use to produce the value; then you could write

dict_three = dict.fromkeys(my_list, factory=lambda: [])

analogous to how defaultdict takes a function to produce the initial value for a new key:

d = defaultdict(list)  # *not* d = defaultdict([])
chepner
  • 497,756
  • 71
  • 530
  • 681