len(dict1 + dict2) does not equal len(dict1) + len(dict2), so using the + operator is nonsense.
len(dict1 + dict2) cannot even be computed by any expression involving +. Using len() to test the semantics of the operation is not arbitrary; the fact that the sizes do not add is a defining quality of a merge. This is a merge, not an addition. The proper analogy is to sets, not lists. The operators should be |, &, and -, exactly as for sets, and the behaviour defined with just three rules: 1. The keys of dict1 [op] dict2 are the elements of dict1.keys() [op] dict2.keys(). 2. The values of dict2 take priority over the values of dict1. 3. When either operand is a set, it is treated as a dict whose values are None. This yields many useful operations and, most importantly, is simple to explain. "sets and dicts can |, &, -" takes up less space in your brain than "sets can |, &, - but dicts can only + and -, where dict + is like set |". merge and update some items: {'a': 1, 'b': 2} | {'b': 3, 'c': 4} => {'a': 1, 'b': 3, 'c': 4} pick some items: {'a': 1, 'b': 2} & {'b': 3, 'c': 4} => {'b': 3} remove some items: {'a': 1, 'b': 2} - {'b': 3, 'c': 4} => {'a': 1} reset values of some keys: {'a': 1, 'b': 2} | {'b', 'c'} => {'a': 1, 'b': None, 'c': None} ensure certain keys are present: {'b', 'c'} | {'a': 1, 'b': 2} => {'a': 1, 'b': 2, 'c': None} pick some items: {'b', 'c'} | {'a': 1, 'b': 2} => {'b': 2} remove some items: {'a': 1, 'b': 2} - {'b', 'c'} => {'a': 1} On Wed, Mar 6, 2019 at 1:51 AM Rémi Lapeyre <remi.lape...@henki.fr> wrote: > Le 6 mars 2019 à 10:26:15, Brice Parent > (cont...@brice.xyz(mailto:cont...@brice.xyz)) a écrit: > > > > > Le 05/03/2019 à 23:40, Greg Ewing a écrit : > > > Steven D'Aprano wrote: > > >> The question is, is [recursive merge] behaviour useful enough and > > > > common enough to be built into dict itself? > > > > > > I think not. It seems like just one possible way of merging > > > values out of many. I think it would be better to provide > > > a merge function or method that lets you specify a function > > > for merging values. > > > > > That's what this conversation led me to. I'm not against the addition > > for the most general usage (and current PEP's describes the behaviour I > > would expect before reading the doc), but for all other more specific > > usages, where we intend any special or not-so-common behaviour, I'd go > > with modifying Dict.update like this: > > > > foo.update(bar, on_collision=updator) # Although I'm not a fan of the > > keyword I used > > Le 6 mars 2019 à 10:26:15, Brice Parent > (cont...@brice.xyz(mailto:cont...@brice.xyz)) a écrit: > > > > > Le 05/03/2019 à 23:40, Greg Ewing a écrit : > > > Steven D'Aprano wrote: > > >> The question is, is [recursive merge] behaviour useful enough and > > > > common enough to be built into dict itself? > > > > > > I think not. It seems like just one possible way of merging > > > values out of many. I think it would be better to provide > > > a merge function or method that lets you specify a function > > > for merging values. > > > > > That's what this conversation led me to. I'm not against the addition > > for the most general usage (and current PEP's describes the behaviour I > > would expect before reading the doc), but for all other more specific > > usages, where we intend any special or not-so-common behaviour, I'd go > > with modifying Dict.update like this: > > > > foo.update(bar, on_collision=updator) # Although I'm not a fan of the > > keyword I used > > This won’t be possible update() already takes keyword arguments: > > >>> foo = {} > >>> bar = {'a': 1} > >>> foo.update(bar, on_collision=lambda e: e) > >>> foo > {'a': 1, 'on_collision': <function <lambda> at 0x10b8df598>} > > > `updator` being a simple function like this one: > > > > def updator(updated, updator, key) -> Any: > > if key == "related": > > return updated[key].update(updator[key]) > > > > if key == "tags": > > return updated[key] + updator[key] > > > > if key in ["a", "b", "c"]: # Those > > return updated[key] > > > > return updator[key] > > > > There's nothing here that couldn't be made today by using a custom > > update function, but leaving the burden of checking for values that are > > in both and actually inserting the new values to Python's language, and > > keeping on our side only the parts that are specific to our use case, > > makes in my opinion the code more readable, with fewer possible bugs and > > possibly better optimization. > > > > > > _______________________________________________ > > Python-ideas mailing list > > Python-ideas@python.org > > https://mail.python.org/mailman/listinfo/python-ideas > > Code of Conduct: http://python.org/psf/codeofconduct/ > _______________________________________________ > Python-ideas mailing list > Python-ideas@python.org > https://mail.python.org/mailman/listinfo/python-ideas > Code of Conduct: http://python.org/psf/codeofconduct/ >
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/