Dictionary union (PEP 584) is merged
github.com
github.com
{**d1, **d2}
is very natural if you also write javascript where their spread operator looks like: {...d1, ...d2}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.
To be fair, you can get that in Python 2 too:
from __future__ import division {**d1, **d2}
because it apparently looks ugly[1].There has been a recent effort to add all these new operators that don't actually let you do anything you couldn't but now you can confuse everyone by doing it in other ways.
{d1, d2} is not intuitive to a primarily-Python developer, and looks nothing like typical Python. The dict unpacking operator it uses is almost never seen outside function arguments.
> There is no such koan. "Only One Way" is a calumny about Python originating long ago from the Perl community.
> There should be one-- and preferably only one --obvious way to do it.
Personally, I’ve always thought that Python missed its Zen, both here and on “explicit is better than implicit.”
Now there are TWO ways of calling a block of code repeatedly based? How confusing for new users. Python really went downhill since then.
The last died with 3.0.
But my point is that the Zen of Python must be seen as a post hoc description overlaid onto whatever the actual Python philosophy is. Aligned, certainly, but at times only roughly aligned.
So I don't see it as having sailed (with string formatting, or other specific even) but never having been there in the first place. More like, sailing in the same waters.
The Tao that can be told
is not the eternal Tao Can the Tao be found
where there is no Tao? def log(fmt, *args):
print(fmt % args)
Hardly a huge change.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.
> 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?
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 usedJust override ‘__and__’ in your whatever class to replace default return.
Pretty explicit in my book.
making the trick work with other mapping types and making it faster is totally understandable though.
dict(d1, **d2)
only works with string keys {**d1,**d2} or dict({**d1,**d2})
works with all key types it seems dict(d1, **d2)
has that problem. it works fine if you unpack into a dict literal: >>> d1 = {1: 'a'}
>>> d2 = {2: 'b'}
>>> {**d1, **d2}
{1: 'a', 2: 'b'}
iirc the pep mostly just says that it's suboptimal because it's syntactically heavy/noisy, non-obvious and can't be overloaded in dict subclasses---
i was curious why the two double-stars behave differently despite syntactic similarity. so i went and checked the bytecode, and it turns out they compile down to different opcodes! `{××d1, ××d2}` yields a BUILD_MAP_UNPACK, while `dict(d1, ××d2)` yields a CALL_FUNCTION_EX/CALL_FUNCTION_KW (depending on the CPython version)
`dict(d1, d2)`
You are calling the dict function, and using the normal syntax for unpacking a dictionary into kwargs. In this case, the name for kwargs must be strings.
def f(list: List[int | str], param: int | None) -> float | str:
pass
f([1, "abc"], None)
https://www.python.org/dev/peps/pep-0604/ {**d1, **d2}
today for the same effect.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.
What made decision makers change their mind and accept this change?
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`).
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.
Is that a joke or are you from PHP world?
Python 3 Community: Look at thing cool dictionary merging thingy!
{**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:> There should be one-- and preferably only one --obvious way to do it.
The operator is better than the dict unpacking-repacking trick, and will become the obvious way to do it.
and dict keys are basically a set
Hence "|" as set union is intuitive for people who are familiar with this application of bit vectors.
[1] https://en.wikipedia.org/wiki/Algebra_of_sets
[2] https://www.britannica.com/science/set-theory/Operations-on-...
You may be interested to read PEP 584's list of examples of all the real-world code the existence of this operator makes clearer: