> For the first two choices one loses commutativity which means that code then suddenly has to have previously cared about it (or it will do the wrong thing)
Since this is a new operator, that shouldn’t be an issue.
I think losing commutivity is okay. After all, d1.update(d2) != d2.update(d1) if keys conflict.
What you have written doesn’t look at all symmetrical but d1 | d2 looks very symmetrical. Operators being symmetrical around a vertical axis tends to imply being commutative (although there are many exceptions e.g. a divide symbol (but note fractions aren’t symmetrical) or a minus sign or using ^ for exponentiation (but superscripting is not symmetrical) or matrix multiplication (but maybe one could argue this is an abbreviation of function application))
Secondly I claim that the issue with using | is that it is not a new operator. It is a new, incompatible meaning for an old operator. Old code might not bother checking that its arg is a set because of it weren’t a set then | or in would fail. New programmers might see dicts as being basically sets and wrongly assume functions for sets would correctly work on dicts.
Since this is a new operator, that shouldn’t be an issue.
I think losing commutivity is okay. After all, d1.update(d2) != d2.update(d1) if keys conflict.