Josh Rosenberg <shadowranger+pyt...@gmail.com> added the comment:

scoder: dict(X, **M) is broken unless M is known to be string keyed (it used to 
work, but in Python 3, it will raise a TypeError). It's part of the argument 
for the additional unpacking generalizations from PEP 448; {**X, **M} does what 
dict(X, **M) is trying to do, but without abusing the keyword argument passing 
convention.

You also claim "It takes me a while to see the dict merge under that heap of 
stars", but that's at least as much about the newness of PEP 448 (and for many 
Python coders, a complete lack of familiarity with the pre-existing varargs 
unpacking rules for functions) as it is about the punctuation; after all, you 
clearly recognize dict(X, **M) even though it's been wrong in most contexts for 
years.

In any event, I'm a strong -1 on this, for largely the same reasons as Raymond 
and others:

1. It doesn't provide any new functionality, just one more way to do it; += is 
satisfied by .update, + is satisfied (more generally and efficiently) by the 
unpacking generalizations

2. It's needlessly confusing; addition is, for all existing types in the 
standard library I can think of, lossless; the information from both sides of 
the + is preserved in some form, either by addition or concatenation (and in 
the concatenation case, addition is happening, just to the length of the 
resulting sequence, and order is preserved). Addition for dictionaries would 
introduce new rules specific to dicts that do not exist for any other type 
regarding loss of values, non-additive resulting length, etc. Those rules would 
likely be similar to those of dict literals and the update method, but they'd 
need to be made explicit. By contrast, the PEP 448 unpacking generalization 
rules followed the existing rules for dict literals; no special rules occur, it 
just behaves intuitively (if you already knew the rules for dict literals 
without unpacking being involved).

3. Almost any generic, duck-typing based code for which addition makes sense 
will not make sense for dicts simply because it loosens the definition of 
addition too much to be useful, so best case, it still raises TypeError (when 
dicts added to non-dict things), worst case, it silently operates in a way that 
violates the rules of both addition and concatenation rather than raising a 
TypeError that the generic code could use to determine the correct thing to do.

4. The already mentioned conflict with Counter (which already has an addition 
operator, with lossless semantics)

5. (Minor) It means PyDict_Type needs a non-NULL tp_as_number, so now it's 
slightly slower to reject dicts as being non-numeric at the C layer

Problem #2 could be used to argue for allowing | instead of + (which would also 
resolve #4, and parts of #3), since | is already used for unioning with sets, 
and this operation is much closer to a union operation than addition or 
concatenation. Even so, it would still be misleading; at least with sets, there 
is no associated value, so it's still mostly lossless (you lose the input 
lengths, but the unique input data is kept); with dicts, you'd be losing values 
too.

Basically, I think the PEP 448 unpacking syntax should remain as the "one-- and 
preferably only one --obvious way to" combine dictionaries as a one-liner. It's 
more composable, since it allows adding arbitrary additional key/value pairs, 
and more efficient, since it allows combining more than two dicts at once with 
no additional temporaries: dicta + dictb + dictc requires "dictab" to be made 
first, then thrown away after dictab + dictc produces dictabc, while {**dicta, 
**dictb, **dictc} builds dictabc directly.

The only real argument I can see for not sticking to unpacking is that it 
doesn't allow for arbitrary dict-like things to produce new dict-like things 
directly; you'd have to rewrap as myspecialdict({**speciala, **specialb}). But 
I don't think that's a flaw worth fixing if it means major changes to the 
behavior of what I'm guessing is one of the three most commonly used types in 
Python (along with int and tuple, thanks to the integration of dicts into so 
many facets of the implementation).

----------
nosy: +josh.r

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue36144>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to