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

Guido van Rossum guido at python.org
Thu Feb 28 23:21:45 EST 2019


On Wed, Feb 27, 2019 at 11:18 PM Serhiy Storchaka <storchaka at gmail.com>
wrote:

> 27.02.19 20:48, Guido van Rossum пише:
> >
> > On Wed, Feb 27, 2019 at 10:42 AM Michael Selik
> > <mike at selik.org
> > <mailto:mike at selik.org>> wrote >     The dict subclass
> collections.Counter overrides the update method
> >     for adding values instead of overwriting values.
> >
> >
> https://docs.python.org/3/library/collections.html#collections.Counter.update
> >
> >     Counter also uses +/__add__ for a similar behavior.
> >
> >          >>> c = Counter(a=3, b=1)
> >          >>> d = Counter(a=1, b=2)
> >          >>> c + d # add two counters together:  c[x] + d[x]
> >          Counter({'a': 4, 'b': 3})
> >
> >     At first I worried that changing base dict would cause confusion for
> >     the subclass, but Counter seems to share the idea that update and +
> >     are synonyms.
> >
> >
> > Great, this sounds like a good argument for + over |. The other argument
> > is that | for sets *is* symmetrical, while + is used for other
> > collections where it's not symmetrical. So it sounds like + is a winner
> > here.
>
> Counter uses + for a *different* behavior!
>
>  >>> Counter(a=2) + Counter(a=3)
> Counter({'a': 5})
>

Well, you can see this as a special case. The proposed + operator on
Mappings returns a new Mapping whose keys are the union of the keys of the
two arguments; the value is the single value for a key that occurs in only
one of the arguments, and *somehow* combined for a key that's in both. The
way of combining keys is up to the type of Mapping. For dict, the second
value wins (not so different as {'a': 1, 'a': 2}, which becomes {'a': 2}).
But for other Mappings, the combination can be done differently -- and
Counter chooses to add the two values.


> 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). Is not this contradicts the Zen?
>

But (as someone else pointed out) {**d1, **d2} always returns a dict, not
the type of d1 and d2.

Also, I'm sorry for PEP 448, but even if you know about **d in simpler
contexts, if you were to ask a typical Python user how to combine two dicts
into a new one, I doubt many people would think of {**d1, **d2}. I know I
myself had forgotten about it when this thread started! If you were to ask
a newbie who has learned a few things (e.g. sequence concatenation) they
would much more likely guess d1+d2.

The argument for + over | has been mentioned elsewhere already.

@Eric Smith <eric at trueblade.com>
> I'd help out.

Please do! I tried to volunteer Stephen d'Aprano but I think he isn't
interested in pushing through a controversial PEP.

The PEP should probably also propose d1-d2.

-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20190228/a0723d0f/attachment-0001.html>


More information about the Python-ideas mailing list