[Python-ideas] Dict joining using + and +=

Raymond Hettinger raymond.hettinger at gmail.com
Sat Mar 2 14:14:18 EST 2019


> On Mar 1, 2019, at 11:31 AM, Guido van Rossum <guido at python.org> wrote:
> 
> 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).

Usually, it's easy to add methods to classes without creating disruption, but ABCs are more problematic.  If MutableMapping grows an __iadd__() method, what would that mean for existing classes that register as MutableMapping but don't already implement __iadd__?  When "isinstance(m, MutableMapping)" returns True, is it a promise that the API is fully implemented? Is this something that mypy could would or should complain about?

> 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

I concur.  The latter is also an eyesore and almost certain to be a stumbling block when reading code.

That said, I'm not sure we actually need a short-cut for "d=e.copy(); d.update(f)".  Code like this comes-up for me perhaps once a year.  Having a plus operator on dicts would likely save me five seconds per year.

If the existing code were in the form of "d=e.copy(); d.update(f); d.update(g); d.update(h)", converting it to "d = e + f + g + h" would be a tempting but algorithmically poor thing to do (because the behavior is quadratic).  Most likely, the right thing to do would be "d = ChainMap(e, f, g, h)" for a zero-copy solution or "d = dict(ChainMap(e, f, g, h))" to flatten the result without incurring quadratic costs.  Both of those are short and clear.

Lastly, I'm still bugged by use of the + operator for replace-logic instead of additive-logic.  With numbers and lists and Counters, the plus operator creates a new object where all the contents of each operand contribute to the result.  With dicts, some of the contents for the left operand get thrown-away.  This doesn't seem like addition to me (IIRC that is also why sets have "|" instead of "+").
 

Raymond




More information about the Python-ideas mailing list