Title: evaluating literal dict with repeated keys gives no warnings/errors
Type: enhancement Stage: resolved
Components: Interpreter Core Versions: Python 3.8, Python 3.7
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: Albert.Ferras, Ramchandra Apte, benjamin.peterson, ebfe, gregory.p.smith, jcea, jfine2358, r.david.murray, remi.lapeyre, rhettinger, terry.reedy
Priority: low Keywords:

Created on 2012-11-02 12:27 by Albert.Ferras, last changed 2019-03-11 15:46 by jfine2358. This issue is now closed.

Messages (17)
msg174507 - (view) Author: Albert Ferras (Albert.Ferras) Date: 2012-11-02 12:27
I normally use dictionaries for configuration purposes in python, but there's a problem where I have a dictionary with many key<->values and one of the keys is repeated.
For example:

lives_in = { 'lion': ['Africa', 'America],
             'parrot': ['Europe'],
             #... 100+ more rows here
             'lion': ['Europe'],
             #... 100+ more rows here

will end up with animal_lives_in['lion'] = 'Europe'. There's no way to detect that I've written a mistake in the code because python won't tell me there's a duplicated key assigned. It's easy to see when you have few keys but hard when you've got many.

I think it should atleast raise a warning when this happens.
msg174519 - (view) Author: Ramchandra Apte (Ramchandra Apte) * Date: 2012-11-02 14:32
This is an unavoidable behaviour of the hash tables (dictionaries)
I don't see much use cases of a warning.
msg174520 - (view) Author: Ramchandra Apte (Ramchandra Apte) * Date: 2012-11-02 14:34
Retract earlier statement. I didn't read the comment fully.
msg174522 - (view) Author: Ramchandra Apte (Ramchandra Apte) * Date: 2012-11-02 14:35
You should be using json for configuration purposes anyway.
This is low priority as only few programs use dictionaries with a gazillion keys.
msg174525 - (view) Author: Albert Ferras (Albert.Ferras) Date: 2012-11-02 14:49
I would use json, but it allows me to set list/strings, etc.. not python objects like I'd want
msg174526 - (view) Author: Albert Ferras (Albert.Ferras) Date: 2012-11-02 14:49
sorry: *it only allows me
msg174528 - (view) Author: Albert Ferras (Albert.Ferras) Date: 2012-11-02 14:51
also, it creates confusion when this happens
msg174530 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2012-11-02 14:57
It is a nice suggestion, but it is also probably a non-trivial change to the parser.  If you want to try coming up with a patch we would consider it, but I suspect there is a limit to how much complexity we'd be willing to add to the parser code for this.

It would also be a backward incompatible change, so it could only go into a new release regardless.

(On the other hand Benjamin might take a look at this and say "oh, that's easy" and make some magic happen.  You never know :)
msg174534 - (view) Author: Lukas Lueg (ebfe) Date: 2012-11-02 15:27
This could be avoided by

lives_in_init = (('lion': ['Africa', 'America']), ('lion': ['Europe']))
lives_in = {}
for k, v in lives_in_init:
    assert k not in lives_in
    lives_in[k] = v
del lives_in_init

Which is fast enough if executed only during module-loading
msg174535 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2012-11-02 15:49
An error is out of the question for compatibility reasons. I think the idea for a warning should be brought up on the python-ideas list. Silently rejecting duplicates has a lot of precedent, though. For example, set literals and the dict constructor:

>>> dict((("dfs", 2), ("dfs", 3)))
{'dfs' : 3}
msg174593 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2012-11-02 22:22
(Benjamin, did you mean 'silently accepting duplicates'?)

Without more use cases and support (from discussion on python-ideas), I think this should be rejected. Being able to re-write keys is fundamental to Python dicts and why they can be used for Python's mutable namespaces. A write-once or write-key-once dict would be something else.

As for literals, a code generator could depend on being able to write duplicate keys without having to go back and erase previous output. A lint-type code checker program could check for duplicate keys. OP: have you checked to see if PyLint or PyChecker or ... already do this? I think this is the appropriate place for such a thing. Lukas' code could be modified to do this also.

Keeping keys alphabetical (possibly within sections) should also solve this specialized problem.
msg174920 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2012-11-05 17:07
FWIW, I agree with this rejection.
msg174955 - (view) Author: Lukas Lueg (ebfe) Date: 2012-11-06 06:29
PyLint or PyChecker can only do this if the keys are all simple objects like ints or strings. Consider a class with a custom __hash__
msg264683 - (view) Author: Gregory P. Smith (gregory.p.smith) * (Python committer) Date: 2016-05-02 23:40
Raising an error on duplicates also has precedent:

>>> dict(a=3, b=4, a=5)
  File "<stdin>", line 1
SyntaxError: keyword argument repeated
msg337332 - (view) Author: Jonathan Fine (jfine2358) * Date: 2019-03-06 17:06
I mention this issue, and related pages, in
[Python-ideas] dict literal allows duplicate keys

It arises from a discussion of PEP 584 -- Add + and - operators to the built-in dict class.

Please send any follow-up to python-ideas (or this issue).
msg337676 - (view) Author: Rémi Lapeyre (remi.lapeyre) * Date: 2019-03-11 15:29
Guido van Rossum said in "this was an explicit design
decision that I made nearly 30 years ago".

I think the best way to avoid silently accepting such values would be to use @gregory.p.smith to use a function call to create the dictionary since duplicate keyword arguments raise an exception there.

I suggest to close this bug report since it works as expected.
msg337679 - (view) Author: Jonathan Fine (jfine2358) * Date: 2019-03-11 15:46
This is was closed and tagged as resolved in 2012. The status has not been changed since then.

Using dict(a=1, ...) provides a workaround, but only when the keys are valid as variable names. The general workaround is something like
        (1, 'a'),
        (2, 'b'),

The helper is necessary:
>>> [(1, 2)] * 5
[(1, 2), (1, 2), (1, 2), (1, 2), (1, 2)]
>>> dict([(1, 2)] * 5)
{1: 2}
Date User Action Args
2019-03-11 15:46:12jfine2358setmessages: + msg337679
2019-03-11 15:29:41remi.lapeyresetnosy: + remi.lapeyre

messages: + msg337676
versions: + Python 3.7, Python 3.8, - Python 3.4
2019-03-06 17:06:45jfine2358setnosy: + jfine2358
messages: + msg337332
2016-05-02 23:40:18gregory.p.smithsetnosy: + gregory.p.smith
messages: + msg264683
2016-05-02 19:00:36r.david.murraylinkissue26910 superseder
2012-11-06 06:29:20ebfesetmessages: + msg174955
2012-11-05 17:07:11rhettingersetnosy: + rhettinger

messages: + msg174920
stage: resolved
2012-11-02 23:15:47benjamin.petersonsetstatus: open -> closed
resolution: rejected
2012-11-02 22:22:48terry.reedysetnosy: + terry.reedy
messages: + msg174593
2012-11-02 17:48:32jceasetnosy: + jcea
2012-11-02 15:49:24benjamin.petersonsetnosy: + benjamin.peterson
messages: + msg174535
2012-11-02 15:27:27ebfesetnosy: + ebfe
messages: + msg174534
2012-11-02 14:57:00r.david.murraysetpriority: normal -> low

type: behavior -> enhancement

title: evaluating dict with repeated keys gives no warnings/errors -> evaluating literal dict with repeated keys gives no warnings/errors
nosy: + r.david.murray
versions: + Python 3.4, - Python 2.7
messages: + msg174530
2012-11-02 14:51:21Albert.Ferrassetmessages: + msg174528
2012-11-02 14:49:56Albert.Ferrassetmessages: + msg174526
2012-11-02 14:49:04Albert.Ferrassetmessages: + msg174525
2012-11-02 14:35:18Ramchandra Aptesetmessages: + msg174522
2012-11-02 14:34:02Ramchandra Aptesetmessages: + msg174520
title: evaluating dict with repeated keys gives no warnings -> evaluating dict with repeated keys gives no warnings/errors
2012-11-02 14:32:16Ramchandra Aptesetnosy: + Ramchandra Apte

messages: + msg174519
title: evaluating dict with repeated keys gives no error/warnings -> evaluating dict with repeated keys gives no warnings
2012-11-02 12:27:47Albert.Ferrascreate