On Friday, March 1, 2019 at 5:47:06 AM UTC-5, Steven D'Aprano wrote: > > On Fri, Mar 01, 2019 at 08:47:36AM +0200, Serhiy Storchaka wrote: > > > Currently Counter += dict works and Counter + dict is an error. With > > this change Counter + dict will return a value, but it will be different > > from the result of the += operator. > > That's how list.__iadd__ works too: ListSubclass + list will return a > value, but it might not be the same as += since that operates in place > and uses a different dunder method. > > Why is it a problem for dicts but not a problem for lists? > > > > Also, if the custom dict subclass implemented the plus operator with > > different semantic which supports the addition with a dict, this change > > will break it, because dict + CustomDict will call dict.__add__ instead > > of CustomDict.__radd__. > > That's not how operators work in Python or at least that's not how they > worked the last time I looked: if the behaviour has changed without > discussion, that's a breaking change that should be reverted. > > Obviously I can't show this with dicts, but here it is with lists: > > py> class MyList(list): > ... def __radd__(self, other): > ... print("called subclass first") > ... return "Something" > ... > py> [1, 2, 3] + MyList() > called subclass first > 'Something' > > > This is normal, standard behaviour for Python operators: if the right > operand is a subclass of the left operand, the reflected method __r*__ > is called first. > > > > Adding support of new operators to builting > > types is dangerous. > > Explain what makes new operators more dangerous than old operators > please. > > > > > I do not understand why we discuss a new syntax for dict merging if > we > > > already have a syntax for dict merging: {**d1, **d2} (which works > with > > > *all* mappings). Is not this contradicts the Zen? > > > > > > > > >But (as someone else pointed out) {**d1, **d2} always returns a dict, > > >not the type of d1 and d2. > > > > And this saves us from the hard problem of creating a mapping of the > > same type. > > What's wrong with doing this? > > new = type(self)() > > Or the equivalent from C code. If that doesn't work, surely that's the > fault of the subclass, the subclass is broken, and it will raise an > exception. > > I don't think it is our responsibility to do anything more than call > the subclass constructor. If that's broken, then so be it. > > > Possibly relevant: I've always been frustrated and annoyed at classes > that hardcode their own type into methods. E.g. something like: > > class X: > def spam(self, arg): > return X(eggs) > # Wrong! Bad! Please use type(self) instead. > > That means that each subclass has to override every method: > > class MySubclass(X): > def spam(self, arg): > # Do nothing except change the type returned. > return type(self)( super().spam(arg) ) > > > This gets really annoying really quickly. Try subclassing int, for > example, where you have to override something like 30+ methods and do > nothing but wrap calls to super. >
I agree with you here. You might want to start a different thread with this idea and possibly come up with a PEP. There might be some pushback for efficiency's sake, so you might have to reel in your proposal to collections.abc mixin methods and UserDict methods. Regarding the proposal, I agree with the reasoning put forward by Guido and I like it. I think there should be: * d1 + d2 * d1 += d2 * d1 - d2 * d1 -= d2 which are roughly (ignoring steve's point about types) * {**d1, **d2} * d1.update(d2) * {k: v for k, v in d1.items() if k not in d2} * for k in list(d1): if k not in d2: del d1[k] Seeing this like this, there should be no confusion about what the operators do. I understand the points people made about the Zen of Python. However, I think that just like with lists, we tend to use l1+l2 when combining lists and [*l1, x, *l2, y] when combining lists and elements. Similarly, I think {**d1, **d2} should only be written when there are also key value pairs, like {**d1, k: v, **d2, k2: v2}. Best, Neil > > -- > Steven > _______________________________________________ > Python-ideas mailing list > python...@python.org <javascript:> > 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/