Thank you to everyone for your patience while I dragged my feet responding to this. It's not because of a lack of interest, just a lack of uninterrupted time to focus on this :-) I believe that the final sticking points are the behaviour with subclasses and whether or not the union operator ought to call "copy" on the left hand operator, or directly on dict. That is, the difference is between *roughly* these two: new = self.copy() # Preserves subclasses. new = dict.copy(self) # Always a builtin dict (But we should use a __copy__ dunder rather than copy.) TL;DR: My *strong* preference is for the union operator to call the left hand operand's copy method, in order to preserve the subclass of the LH operand, but if that's a sticking point for the proposal I'll accept the alternative, non-preserving, behaviour. On Thu, Feb 06, 2020 at 07:38:03PM -0000, Brandt Bucher wrote:
One issue that's come up during PR review with Guido and Serhiy is, when evaluating `a | b`, whether or not the default implementation should call an overridden `copy()` method on `a` in order to create an instance of the correct subclass (rather than a plain-ol' `dict`). For example, `defaultdict` works correctly without any additional modification:
My opinion is that Python built-in types make subclassing
unnecessarily(?) awkward to use, and I would like to see that change.
For example, consider subclassing float. If you want your subclass to be
actually usable, you have to write a whole bunch of boilerplate,
otherwise the first time you perform arithmetic on your subclass, it
will be converted to a regular old float.
class MyFloat(float):
# This is the only thing I actually want to change.
def mymethod(self): pass
# But I need to override every operator too.
def __add__(self, other):
tmp = super().__add__(other)
if tmp is NotImplemented:
return tmp
return MyFloat(tmp)
# and so on for all the other operators
This is painful and adds a great amount of friction to subclassing.
A more pertinent example, from dict itself:
py> class MyDict(dict):
... pass
...
py> d = MyDict()
py> type(d.copy())
So this has immediate benefits for both usability and maintenance: subclasses only need to override `copy()` to get working `__or__`/`__ror__` behavior.
Indeed, except it should be the dunder `__copy__`. -- Steven