Reputation: 390
I'm learning Python, currently dictionary comprehension. I am playing around with different ideas just to see what I get and I'm getting one I really don't understand. Any help understanding what I'm doing wrong would be really appreciated.
Specifically, this code:
test_dict = {key: val
for key in ['a','b','c']
for val in range(3)}
print(test_dict)
Produces the following dictionary: {'a': 2, 'b': 2, 'c': 2}
I'm expecting: {'a': 0, 'b': 1, 'c': 2}
When I run this quick loop:
for val in range(3):
print(val)
I get:
0
1
2
Is there a reason every dictionary key is getting the same value, the final value of the range iterator?
I'm running Python 3.6.5 via Anaconda / Jupyter notebooks.
Upvotes: 0
Views: 55
Reputation: 184131
Let's blow up your dict comprehension; it's equivalent to the following:
test_dict = {}
for key in ['a','b','c']:
for val in range(3):
test_dict[key] = val
So, for each key, you perform three different assignments into your dictionary. Naturally, only the last one is retained.
To get the result you want, just assign ho each key once. An obvious way in this case is to use enumerate()
to number the items in the sequence, then use that for the value.
test_dict = {key: val for val, key in enumerate(['a','b','c'])}
For the general case of any two sequences, use zip()
:
test_dict = {key: val for key, val in zip(['a', 'b', 'c'], range(3))}
Actually, since the dict
constructor is happy to consume a sequence of key/value pairs, you can write that this way:
test_dict = dict(zip(['a', 'b', 'c'], range(3)))
Upvotes: 4
Reputation: 15071
Your code is equivalent to a 2 nested for
loops, for each key
you effectively run successively the command test_dict[key] = val
for all val
, only the last one will remain.
You probably want this instead:
test_dict = {key: val for key,val in zip('abc', range(3))}
or directly
test_dict = dict(zip('abc', range(3)))
Upvotes: 2