[Python-ideas] PEP: Dict addition and subtraction

James Edwards jheiv at jheiv.com
Fri Mar 8 23:49:28 EST 2019


On Fri, Mar 8, 2019 at 11:25 AM João Matos <jcrmatos at gmail.com> wrote:

> I've just read your PEP 585 draft and have some questions.
> When you say
> "
>
> Like the merge operator and list concatenation, the difference operator
> requires both operands to be dicts, while the augmented version allows any
> iterable of keys.
>
> >>> d - {'spam', 'parrot'}
> Traceback (most recent call last):
>   ...
> TypeError: cannot take the difference of dict and set
>
> >>> d -= {'spam', 'parrot'}
> >>> print(d)
> {'eggs': 2, 'cheese': 'cheddar'}
>
> >>> d -= [('spam', 999)]
> >>> print(d)
> {'spam': 999, 'eggs': 2, 'cheese': 'cheddar', 'aardvark': 'Ethel'}
>
>
> "
>
> The option d -= {'spam', 'parrot'} where parrot does not exist in the d
> dict, will raise an exception (eg. KeyNotFound) or be silent?
>
> The option d -= [('spam', 999)] should remove the pair from the dict,
> correct? But the print that follows still shows it there. It's a mistake or
> am I missing something?
>

My understanding is that:

 - (Q1) Attempting to discard a key not in the target of the augmented
assignment would *not *raise a KeyError (or any Exception for that
matter).  This is analogous to how the - operator works on sets and is
consistent with the pure python implementation towards the bottom of the
PEP.
 - (Q2) This one got me as well while implementing the proposal in cpython,
but there is a difference in what "part" of the RHS the operators "care
about" if the RHS isn't a dict.  The += operator expects 2-tuples and will
treat them as (key, value) pairs.  The -= operator doesn't attempt to
unpack the RHS's elements as += does and expects keys.  So d -= [('spam',
999)] treated the tuple as a *key *and attempted to discard it.

IOW,

    d = {
        'spam': 999,
        ('spam', 999): True
    }
    d -= [('spam', 999)]

Would discard the *key* ('spam', 999) and corresponding value True.

Which highlights a possibly surprising incongruence between the operators:

    d = {}
    update = [(1,1), (2,2), (3,3)]
    d += update
    d -= update
    assert d == {}  # will raise, as d still has 3 items

Similarly,

    d = {}
    update = {1:1, 2:2, 3:3}
    d += update.items()
    d -= update.items()
    assert d == {}  # will raise, for the same reason
    d -= update.keys()
    assert d == {}  # would pass without issue

That being said I (personally) wouldn't consider it a deal-breaker and
still would very much appreciate of the added functionality (regardless of
the choice of operator).

- Jim
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20190308/2aacf31b/attachment-0001.html>


More information about the Python-ideas mailing list