On Thu, Feb 28, 2019 at 10:30 PM Serhiy Storchaka <storchaka@gmail.com> wrote:
28.02.19 23:19, Greg Ewing пише:
> Serhiy Storchaka wrote:
>> I do not understand why we discuss a new syntax for dict merging if we
>> already have a syntax for dict merging: {**d1, **d2} (which works with
>> *all* mappings).
> But that always returns a dict. A '+' operator could be implemented
> by other mapping types to return a mapping of the same type.

And this opens a non-easy problem: how to create a mapping of the same
type? Not all mappings, and even not all dict subclasses have a copying

There's a compromise solution for this possible. We already do this for Sequence and MutableSequence: Sequence does *not* define __add__, but MutableSequence *does* define __iadd__, and the default implementation just calls self.update(other). I propose the same for Mapping (do nothing) and MutableMapping: make the default __iadd__ implementation call self.update(other).

Looking at the code for Counter, its __iadd__ and __add__ behave subtly different than Counter.update(): __iadd__ and __add__ (and __radd__) drop values that are <= 0, while update() does not. That's all fine -- Counter is not bound by the exact same semantics as dict (starting with its update() method, which adds values rather than overwriting).

Anyways, the main reason to prefer d1+d2 over {**d1, **d2} is that the latter is highly non-obvious except if you've already encountered that pattern before, while d1+d2 is what anybody familiar with other Python collection types would guess or propose. And the default semantics for subclasses of dict that don't override these are settled with the "d = d1.copy(); d.update(d2)" equivalence.

--Guido van Rossum (python.org/~guido)