Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a python dict comprehension always "last wins" if there are duplicate keys

If I create a python dictionary with a dict comprehension, but there are duplicate keys, am I guaranteed that the last item will be the one that ends up in the final dictionary? It's not clear to me from looking at https://www.python.org/dev/peps/pep-0274/?

new_dict = {k:v for k,v in [(1,100),(2,200),(3,300),(1,111)]}
new_dict[1] #is this guaranteed to be 111, rather than 100?
like image 233
user2667066 Avatar asked Sep 24 '16 16:09

user2667066


People also ask

Does Python dictionary accept duplicate keys?

The straight answer is NO. You can not have duplicate keys in a dictionary in Python.

Can ordered Dict have duplicate keys?

Dictionary items are ordered, changeable, and does not allow duplicates. Dictionary items are presented in key:value pairs, and can be referred to by using the key name.

Is dictionary comprehension faster than for loop?

List comprehensions are faster than for loops to create lists. But, this is because we are creating a list by appending new elements to it at each iteration.

What is dict comprehension in Python?

Dictionary comprehension is a method for transforming one dictionary into another dictionary. During this transformation, items within the original dictionary can be conditionally included in the new dictionary and each item can be transformed as needed.


2 Answers

The last value for a key wins. The best documentation I can find for this is in the Python 3 language reference, section 6.2.7:

A dict comprehension, in contrast to list and set comprehensions, needs two expressions separated with a colon followed by the usual “for” and “if” clauses. When the comprehension is run, the resulting key and value elements are inserted in the new dictionary in the order they are produced.

That documentation also explicitly states that the last item wins for comma-separated key-value pairs ({1: 1, 1: 2}) and for dictionary unpacking ({**{1: 1}, **{1: 2}}):

If a comma-separated sequence of key/datum pairs is given, ... you can specify the same key multiple times in the key/datum list, and the final dictionary’s value for that key will be the last one given.

A double asterisk ** denotes dictionary unpacking. Its operand must be a mapping. Each mapping item is added to the new dictionary. Later values replace values already set by earlier key/datum pairs and earlier dictionary unpackings.

Note that as wim points out, the first version of a key wins if there are equal but distinct keys:

>>> {k: v for k, v in [(1, 1), (1.0, 2.0)]}
{1: 2.0}

Here, the final dict has the key from (1, 1), but the value from (1.0, 2.0).

like image 155
user2357112 supports Monica Avatar answered Oct 18 '22 03:10

user2357112 supports Monica


am I guaranteed that the last item will the the one that ends up in the final dictionary?

Not exactly...

In case of duplicate keys, the first key is preserved, and the last value is preserved. The resulting item (key, value) may not have been present in any of the original pairs in the first place.

>>> {1.0: 1, 1: 1.0}
{1.0: 1.0}

This behaviour somewhat documented under Dictionary displays (emphasis mine):

This means that you can specify the same key multiple times in the key/datum list, and the final dictionary’s value for that key will be the last one given.

like image 23
wim Avatar answered Oct 18 '22 04:10

wim