
Dictionary union (PEP 584) is merged - whalesalad
https://github.com/python/cpython/pull/12088
======
fyp

      {**d1, **d2}
    

is very natural if you also write javascript where their spread operator looks
like:

    
    
      {...d1, ...d2}

~~~
whalesalad
This is reason enough to upgrade from Python 2.7 if you are still on it. I use
this convenience almost daily.

~~~
TylerE
No it isn’t.

~~~
tempay
One of the issues with Python 3 is that there isn’t really one killer feature,
it’s countless little ones. Many believe 3.6 was the first release where they
added up to enough of a benefit (though f-strings are a big help for many
projects).

Regardless it no longer matters, the Python 2 ecosystem is now rotting as
packages drop support. Every week I have to make one or two hot fixes
somewhere to forcibly pin to an old version to fix something.

~~~
edudobay
For me, proper handling and distinction of Unicode vs. binary data was a game
changer. I don't know if that's related to my first language being non-
English, but I remember it being really important to me and a strong reason
why I made the switch years ago.

~~~
heavenlyblue
I used to work for a huge SEM business working with keywords in all languages
of the world. No-brainer.

------
kam
The PEP document describing the feature:
[https://www.python.org/dev/peps/pep-0584/](https://www.python.org/dev/peps/pep-0584/)

~~~
pansa2
> > Dict union will violate the Only One Way koan from the Zen.

> There is no such koan. "Only One Way" is a calumny about Python originating
> long ago from the Perl community.

~~~
ehsankia
That ship had long sailed with string formatting anyways.

~~~
orf
F-strings are the one obvious way to do string formatting. There may be other
ways, for legacy backwards compatibility reasons, but f-strings are _the_ way
to do string formatting.

~~~
cochne
I disagree. In logging for example, ‘%s’ with the value as an argument to the
logger is preferred because the formatting can be ignored if the log level is
not sufficient to print.

~~~
orf
Log formatting is a different problem than string formatting. With log
formatting you pass the formatting arguments as function parameters, which is
completely different from any other way you format strings.

~~~
AlexandrB
I think you're getting downvoted because logging is basically doing:

    
    
        def log(fmt, *args):
            print(fmt % args)
    

Hardly a huge change.

------
misnome
Fantastic. Especially glad they went with | over +, that’s always felt like
the natural way I’ve wanted to do this. Looking forward to more set-like
operators in the future!

~~~
kbd
Thank goodness sanity prevailed on the operator!

We had a whole discussion on HN last time[1] about this, where I argued that
dicts are logically subclasses of sets and therefore should share operators.

When I saw this headline I accepted my fate of typing the "wrong" operator
from now on and liking Python just a tiny bit less for the inconsistency. So
glad they reconsidered.

[1]
[https://news.ycombinator.com/item?id=19314646](https://news.ycombinator.com/item?id=19314646)

~~~
mixmastamyk
Guido stated his preference to | and the pep was changed.

------
kbd
The PEP has this section:

> The new operators will have the same relationship to the dict.update method
> as the list concatenate (+) and extend (+=) operators have to list.extend.
> Note that this is somewhat different from the relationship that |/|= have
> with set.update; the authors have determined that allowing the in-place
> operator to accept a wider range of types (as list does) is a more useful
> design, and that restricting the types of the binary operator's operands
> (again, as list does) will help avoid silent errors caused by complicated
> implicit type casting on both sides.

Would someone please explain what they mean with regard to being different
from set.update, and what could lead to silent errors?

------
seemslegit
I wouldn't have thought about dict unpacking as a solution either but once
suggested it seems satisfactory and I don't see how adding a new operator is
more discoverable or natural than just putting this method in a more prominent
place in the documentation.

~~~
Znafon
Guido himself said he had forgotten about this trick and since it's syntactic
sugar, it does not respect dict subclasses or other mappings.

~~~
seemslegit
imo

    
    
      defaultdict(callback,{**a,**b}) 
    

is more readable than a | b without knowing that a or b are defaultdicts and
having to reason about which default callback will be used

~~~
anonymoushn
Note that a | b is already a disaster if you try to use subclasses of set. In
python 2.7, iirc it would return a set of a's type but without calling the
constructor. In python 3 it seems to return a set (not the type of a or the
type of b).

~~~
CameronNemo
Not sure about the set operator, but this operator is meant to handle
subclasses better than the status quo.

------
Rotareti
I wish there was a union operator for typing as well to replace `Union[str,
int]` with just `[str|int]`.

~~~
ash
PEP 604 (draft) proposes this:

    
    
      def f(list: List[int | str], param: int | None) -> float | str:
          pass
    
      f([1, "abc"], None)
    

[https://www.python.org/dev/peps/pep-0604/](https://www.python.org/dev/peps/pep-0604/)

------
ptx
Yay! I was wishing for this feature just a few days ago. It's somewhat
analogous to how _sorted_ (since Python 2.4) frees us from having to tediously
make copies of lists to sort them in place.

~~~
gnulinux
You can already do

    
    
       {**d1, **d2}
    

today for the same effect.

~~~
CameronNemo
Here I was wondering what a dictionary union was, already having stumbled upon
to it and used it.

Note that the method you show is slightly different for cases of dict
subclasses.

The PEP notes the difference:
[https://www.python.org/dev/peps/pep-0584/#d1-d2](https://www.python.org/dev/peps/pep-0584/#d1-d2).

------
wodenokoto
I haven’t read the entire bug tracking thread, but it seems like people were
mostly against it, and have been many times in the past.

What made decision makers change their mind and accept this change?

~~~
_-___________-_
Most of the bug tracking thread was just about whether `somedictsubclass() |
somedictsubclass()` should be `dict()` or `somedictsubclass()`

The latter (returns `somedictsubclass`) would cause the `|` operator to rely
on the `copy()` method from `dict` which would be the only case where an
operator relies on a non-double-underscores method. Based on that, two core
devs were against it. The core devs prevailed, and the behaviour will be the
former (returns `dict`).

------
mrweasel
It seems that just using + as the operator was reject because it's: "Too
specialised to be used as the default behavior."

What does that mean? It works for lists, obviously lists don't need to worry
about duplicated values, but it's kind non-intuitive that + won't work for
dicts. It think many people view dicts and lists as the same general type of
data structure.

~~~
heavenlyblue
>> It think many people view dicts and lists as the same general type of data
structure.

Is that a joke or are you from PHP world?

------
speedplane
Python 2 Community: We are in hell, we have to stop working on everything to
upgrade to Python 3, there is no straightforward way to upgrade, many of our
python 2 libraries haven't been updated, and there are tons of little bugs
that are hard to fix.

Python 3 Community: Look at thing cool dictionary merging thingy!

------
saagarjha
What does this do on duplicate keys? Keep one? Take a predicate?

~~~
realslimjd
It keeps the one on the right. They explain it in the PEP:
[https://www.python.org/dev/peps/pep-0584/](https://www.python.org/dev/peps/pep-0584/)

~~~
mixmastamyk
AKA Last one wins.

------
camgunz
Can't wait for Python 4k where we TOOWTDI all the old stuff.

------
fulafel
The problem with sprinkling operator overloading all over the place in non
numerical use is that you as tje reader don't get the context hints provided
by method names. I think this change is bad in the overall balance.

~~~
kbd
The best way to do dictionary union is already symbolic:

    
    
        {**d1, **d2}
    

This provides a clearer symbolic notation for dictionaries analogous to what's
already available with sets. FWIW the pep discusses what this would look like
as a method vs an operator:

[https://www.python.org/dev/peps/pep-0584/#use-a-
method](https://www.python.org/dev/peps/pep-0584/#use-a-method)

~~~
fulafel
The best way for in my view is .union(), the new syntax additions are too
cryptic.

~~~
choward
I agree. Back in the day when I used Ruby, I remember one of the arguments for
Python being their belief that there should be one way to do things. Found one
reference:

> There should be one-- and preferably only one --obvious way to do it.

[https://www.python.org/dev/peps/pep-0020/](https://www.python.org/dev/peps/pep-0020/)

~~~
orf
There should be one _obvious_ way to do things. Not _one_ way to do things.

The operator is better than the dict unpacking-repacking trick, and will
become the obvious way to do it.

------
anentropic
Nice

------
iddan
FINALLY!

