5 ms·
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 di
by seemslegit 7y ago
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 7y agoGuido himself said he had forgotten about this trick and since it's syntactic sugar, it does not respect dict subclasses or other mappings.
- seemslegit 7y agoimo 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 7y agoNote 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 7y agoNot sure about the set operator, but this operator is meant to handle subclasses better than the status quo.
- mdrachuk 7y agoWow, one more point for python 3. Just override ‘__and__’ in your whatever class to replace default return. Pretty explicit in my book.
- orf 7y agoIt’s also really expensive. This new operator works with any Mapping type without needing silly hacks.
- blackandblue 7y agothe easy to forget justification is surprising to me. especially when most modern languages have the concept of unpacking, rest, spread or etc. making the trick work with other mapping types and making it faster is totally understandable though.
- banannaise 7y agoIt's pretty obvious with the context of other languages, but wildly outside the norm for Python. I rarely see dict unpacking outside function signatures.
- war1025 7y agoIt mentions in the PEP discussion that the {a, b} trick only works for string keys. So it isn't applicable in as many cases as the new operator.
- seemslegit 7y agodict(d1, **d2) only works with string keys {**d1,**d2} or dict({**d1,**d2}) works with all key types it seems
- uryga 7y agoactually, only 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)
- dahfizz 7y agoThis seems pretty straightforward. When doing `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.
- uryga 7y agoyeah, that side of the (in)equation was pretty obvious, i was mostly interested in the `{...}` one. i admit that a bytecode listing probably isn't the best exposition, i just like digging into VM stuff :)