Most Pythonic Way to Build Dictionary From Single List

I have a list of day names (typically Monday-Saturday, though special cases apply) that I want to create a dictionary out of. I want to initialize the value of each day to zero.

If I had a list of zeroes the same length of the list of days, this would be a simple use case of zip(). However, a list of zeroes is a waste of space, and if that were the only solution I'd just as soon do something like:

for day in weekList:
    dayDict[day] = 0

Is there a more pythonic way?


Solution 1:

Use the .fromkeys() class method:

dayDict = dict.fromkeys(weekList, 0)

It builds a dictionary using the elements from the first argument (a sequence) as the keys, and the second argument (which defaults to None) as the value for all entries.

By it's very nature, this method will reuse the value for all keys; don't pass it a mutable value such as a list or dict and expect it to create separate copies of that mutable value for each key. In that case, use a dict comprehension instead:

dayDict = {d: [] for d in weekList}

Solution 2:

Apart from dict.fromkeys you can also use dict-comprehension, but fromkeys() is faster than dict comprehensions:

In [27]: lis = ['a', 'b', 'c', 'd']

In [28]: dic = {x: 0 for x in lis}

In [29]: dic
Out[29]: {'a': 0, 'b': 0, 'c': 0, 'd': 0}

For 2.6 and earlier:

In [30]: dic = dict((x, 0) for x in lis)

In [31]: dic
Out[31]: {'a': 0, 'b': 0, 'c': 0, 'd': 0}

timeit comparisons:

In [38]: %timeit dict.fromkeys(xrange(10000), 0)         # winner
1000 loops, best of 3: 1.4 ms per loop

In [39]: %timeit {x: 0 for x in xrange(10000)}
100 loops, best of 3: 2.08 ms per loop

In [40]: %timeit dict((x, 0) for x in xrange(10000))
100 loops, best of 3: 4.63 ms per loop

As mentioned in comments by @Eumiro and @mgilson it is important to note that fromkeys() and dict-comprehensions may return different objects if the values used are mutable objects:

In [42]: dic = dict.fromkeys(lis, [])

In [43]: [id(x) for x in dic.values()]
Out[43]: [165420716, 165420716, 165420716, 165420716] # all point to a same object

In [44]: dic = {x: [] for x in lis}

In [45]: [id(x) for x in dic.values()]
Out[45]: [165420780, 165420940, 163062700, 163948812]  # unique objects