[Python-ideas] PEP: Dict addition and subtraction

Jonathan Fine jfine2358 at gmail.com
Wed Mar 6 09:49:40 EST 2019

Michael Lee wrote:

> If your instinct is to assume "+" means "concatenation", then it would be natural to assume that {"a": 1, "b": 2} + {"c": 3, "b": 4} would be identical to {"a": 1, "b": 2, "c": 3, "b": 4} -- literally concat the key-value pairs into a new dict.

> But of course, you can't have duplicate keys in Python. So, you would either recall or look up how duplicate keys are handled when constructing a dict and learn that the rule is that the right-most key wins. So the natural conclusion is that "+" would follow this existing rule -- and you end up with exactly the behavior described in the PEP.

This is a nice argument. And well presented. And it gave me surprise,
that taught me something. Here goes:

    >>> {'a': 0}
    {'a': 0}
    >>> {'a': 0, 'a': 0}
    {'a': 0}
    >>> {'a': 0, 'a': 1}
    {'a': 1}
    >>> {'a': 1, 'a': 0}
    {'a': 0}

This surprised me quite a bit. I was expecting to get an exception. However

    >>> dict(a=0)
    {'a': 0}
    >>> dict(a=0, a=0)
    SyntaxError: keyword argument repeated

does give an exception.

I wonder, is this behaviour of {'a': 0, 'a': 1} documented (or tested)
anywhere? I didn't find it in these URLs:

I think this behaviour might give rise to gotchas. For example, if we
define inverse_f by
    >>> inverse_f = { f(a): a, f(b): b }
then is the next statement always true (assuming a <> b)?
    >>> inverse_f[ f(a) ] == a

Well, it's not true with these values
    >>> a, b = 1, 2
    >>> def f(n): pass # There's a bug here, f(n) should be a bijection.

A quick check that len(inverse) == 2 would provide a sanity check. Or
perhaps better, len(inverse_f) == len(set(a, b)). (I don't have an
example of this bug appearing 'in the wild'.)

Once again, I thank Michael for his nice, instructive and
well-presented example.

More information about the Python-ideas mailing list