[Python-ideas] PEP: Dict addition and subtraction

David Mertz mertz at gnosis.cx
Wed Mar 6 07:52:17 EST 2019


I strongly agree with Ka-Ping. '+' is intuitively concatenation not
merging. The behavior is overwhelmingly more similar to the '|' operator in
sets (whether or not a user happens to know the historical implementation
overlap).

I think growing the full collection of set operations world be a pleasant
addition to dicts. I think shoe-horning in plus would always be jarring to
me.

On Wed, Mar 6, 2019, 5:30 AM Ka-Ping Yee <zestyping at gmail.com> wrote:

> 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.lapeyre at henki.fr> wrote:
>
>> Le 6 mars 2019 à 10:26:15, Brice Parent
>> (contact at brice.xyz(mailto:contact at 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
>> (contact at brice.xyz(mailto:contact at 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 at python.org
>> > https://mail.python.org/mailman/listinfo/python-ideas
>> > Code of Conduct: http://python.org/psf/codeofconduct/
>> _______________________________________________
>> Python-ideas mailing list
>> Python-ideas at python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20190306/da08d3bb/attachment-0001.html>


More information about the Python-ideas mailing list