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

M.-A. Lemburg mal at egenix.com
Wed May 4 10:18:59 EDT 2016


On 04.05.2016 16:00, Steven D'Aprano wrote:
> On Wed, May 04, 2016 at 02:37:56PM +0200, M.-A. Lemburg wrote:
>> On 04.05.2016 14:15, Steven D'Aprano wrote:
>>> On Wed, May 04, 2016 at 01:56:56PM +0200, M.-A. Lemburg wrote:
>>>
>>>> Issuing a warning for this would probably help, but raising
>>>> an error introduced a backwards incompatibility which is
>>>> not warranted IMO, given how seldom such situations occur in
>>>> practice.
> 
> I agree with you that an error is unjustified but a warning might be.
> 
> 
>>>> For the implementation, there are two possibilities I can think
>>>> of:
>>>>
>>>> 1. have STORE_MAP run a test for an already existing entry
>>>>    and issue a warning
> 
> You have suggested that's too expensive, so I'm happy to rule that out.
> 
> 
>>>> 2. add a final CHECK_MAP byte code to check that the number
>>>>    of keys in the mapping correspond to the number of keys
>>>>    added via the dict literal
> [...]
>>>> The second one is cheap regarding performance, but may not
>>>> be accurate, since STORE_MAP may well be working on dynamically
>>>> generated keys. It does work well for constants, and if we're
>>>> just issuing a warning, may be good enough.
>>>
>>> I'm not sure I understand what you mean by this. Are you suggesting that 
>>> if I write:
>>>
>>> {1: None, 1: None}
>>>
>>> Python knows that it got two keys as argument, and so 
>>> CHECK_MAP can determine that there is a duplicate? (i.e. that 2 keys 
>>> were arguments, but the finished dict only has length 1). But if I 
>>> write:
>>>
>>> {x: None, x: None}
>>>
>>> Python *cannot* tell that there were two keys given (since they are 
>>> expressions, not constants) and CHECK_MAP can't do anything?
>>
>> Well, the CHECK_MAP byte code would only check whether the number
>> of assignments you are doing is equal to the number of keys
>> found in the final dict. That's a very coarse test and not
>> perfect. It can also not tell you which key causes the
>> mismatch.
>>
>> On the plus side, the extra check is a simply size check
>> and doesn't have to be applied per added mapping.
> 
> Sorry MAL, perhaps I'm a bit slow tonight, but I'm still lost. {x: None, 
> x: None} -- would CHECK_MAP detect that as a duplicate or not?
> 
> If the answer is "Yes", then this seems to me to be a cheap way of 
> detecting the existence of at least one duplicate (but not which key was 
> duplicate). That strikes me as good enough, in which case I would 
> support raising a warning.

Yes:

>>> dis.dis('{x:None, x:None}')
  1           0 BUILD_MAP                2
              3 LOAD_CONST               0 (None)
              6 LOAD_NAME                0 (x)
              9 STORE_MAP
             10 LOAD_CONST               0 (None)
             13 LOAD_NAME                0 (x)
             16 STORE_MAP
             17 RETURN_VALUE
>>> d = {x:None, x:None}
>>> len(d)
1

Since 1 != 2 -> issue warning

We'd just have to tell the CHECK_MAP byte code to check
for len(map) == 2. The byte code compiler will be able to
determine this and add the correct byte code entry.

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, May 04 2016)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...           http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...           http://zope.egenix.com/
________________________________________________________________________

::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
           Registered at Amtsgericht Duesseldorf: HRB 46611
               http://www.egenix.com/company/contact/
                      http://www.malemburg.com/



More information about the Python-ideas mailing list