[Python-ideas] dictionary constructor should not allow duplicate keys

Terry Reedy tjreedy at udel.edu
Tue May 3 23:23:39 EDT 2016

On 5/3/2016 8:46 PM, Luigi Semenzato wrote:
> On Tue, May 3, 2016 at 4:51 PM, Steven D'Aprano <steve at pearwood.info> wrote:

The thread seems to partly be based on a confusion between literals and 
displays, which led to dict displays being called dict literals.  A 
literal defines an int or string at the initial lexing or tokenizing 
phase of the parser.  A display, like comprehensions, abbreviates 
runtime code for creating a composite collection object.

>> What counts as "duplicate keys"?  I presume that you mean that two keys
>> count as duplicate if they hash to the same value, and are equal. But
>> you keep mentioning "literals" -- does this mean you care more about
>> whether they look the same rather than are the same?
> Correct.  The errors that I am guessing matter the most are those for
> which folks copy-paste a key-value pair, where the key is a literal
> string, intending to change the key, and then forget to change it.
>> # duplicate literals, forbidden
>> d = {100: 1, 100: 2}
> Correct.  Possibly caught during parsing.

The above is equivalent to and an abbreviation of

d = {}; d[100] = 1; d[100] = 2

A bit silly, but quite legal.  Every value replacement necessarily 
involves a 'duplicate key'.  Both of the above are also equivalent to

d = {a:b for a,b in ((100,1), (100,2))}

This is also equivalent to

d = {}
for a, b in ((100,1), (100,2)):
     d[a] = b

which is close to the python version of how the comprehension would 
implemented in python.

Here is a 5th version, which I expect is close to the actual CPython 
code for a dict display.

tem = [100, 1, 100, 2]  # as in the top of the virtual machine stack
n = 4  # number of items in display = 2 * number of pairs
d = {}
for i in range(-n, 0, 2):
     d[tem[i]] = tem[i+1]

We have 5 equivalent snippets, each of which could have the same bug. 
Why single out just one to raise an exception?  My guess is that it is 
partly from mistakenly thinking of the one as a like a lexer literal 
rather than as runtime code.

Terry Jan Reedy

More information about the Python-ideas mailing list