Hi Brandt, very nice PEP. I have two questions here.

First:

> - The proposal in its current form is very easy to wrap your head around: "|" 
> takes dicts, "|=" takes anything dict.update does.

I see this asymmetry between the | and |= mentioned a few times in the
PEP, but I don't see any rationale other than "the authors have
decided". I am not saying that this is the wrong decision, but the
reasoning behind this choice is not obvious, and I think it might be a
good idea to include the rationale in the PEP. I'd say the asymmetry
between list's `__add__` and `__iadd__` semantics is actually fairly
confusing for anyone who hasn't encountered it before:

    >>> a = []
    >>> a = a + "one"                                         
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent
    call last)
    <ipython-input-5-f2c4cda7ee5b> in <module>
    ----> 1 a = a + "one"

    TypeError: can only concatenate list (not "str") to list
    >>> a += "one"
    >>> a
    ['o', 'n', 'e']

I think most people would be surprised at the difference in semantics
here and this also an example of a situation where it's not obvious that
the "call `list.extend`" behavior is the right thing to do. It would be
nice to see why you rejected:

1. Giving |= `.update` semantics rather than the semantics you chose for |.

2. Giving `|` the same semantics as `|=`.

Second question:

The specification mentions "Dict union will return a new dict containing
the left operand merged with the right operand, which must be a dict (or
an instance of a dict subclass)." Can you clarify if it is part of the
spec that it will always return a `dict` even if one or both of the
operands is a dict subclass? You mentioned in another post that this is
deliberately intended to be subclass-friendly, but if it always returns
`dict`, then I would expect this:

    >>> class MyDict(dict):
    ...    pass
    ...
    >>> MyDict({1: 2}) | MyDict({3: 4})
    {1: 2, 3: 4}

I realize that there's a lot of precedent for this with other builtin
types (int subclasses reverting to int with +, etc), though generally
the justifications for this are two-fold:

1. For symmetrical operations like addition it's not obvious which
operand's type should prevail, particularly if the two are both
different dict subclasses. I think in this case | is already
asymmetrical and it would be relatively natural to think of the right
thing to do as "make a copy of the LHS then update it with the RHS"
(thus retaining the subtype of the LHS).

2. Subclasses may override the constructor in unpredictable ways, so we
don't know how to construct arbitrary subtypes. I /think/ this objection
could be satisfied by using logic equivalent to `copy.copy` for the LHS
when it is a dict subclass, and then using the mapping protocol on the RHS.

Unless there is compelling reason to do otherwise, I am in favor of
trying to retain subclass identity after operations, but either way it
would be good to be explicit about it in the specification and maybe
include a bit of the rationale one way or the other.

Best,
Paul

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/L44V6WTFI4OWM7TPYIMCACJHKBRJQMIU/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to