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: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict https://docs.python.org/3/tutorial/datastructures.html#dictionaries

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.