On Thu, Jul 5, 2018 at 3:45 PM Nick Coghlan <ncogh...@gmail.com> wrote:
> > > On Thu., 5 Jul. 2018, 3:17 pm Guido van Rossum, <gu...@python.org> wrote: > >> Let me be slightly contrarian. :-) >> >> On Wed, Jul 4, 2018 at 9:12 PM Chris Angelico <ros...@gmail.com> wrote: >> >>> Definitely against augmentation, for several reasons: >>> >>> 1) Spelling - should it be :+= or +:= ? >>> >> >> That one's easy. As Nick's (withdrawn) PEP 577 shows it should be simply >> `+=`. >> >> >>> 2) Is the result of the expression the modified value or the original? >>> >> >> Someone (sadly I forget who) showed, convincingly (to me anyways :-) that >> it should return whatever the `__iadd__` method returns, or (if there isn't >> one) the result of `a = a + b`. >> > > I think I had it as an open question in one of the earlier drafts of PEP > 577. > > The subsequent rationale for it returning the modified value was that we > have this existing equivalence at the statement level: > > a += b > a = operator.iadd(a, b) > > So the natural expression level semantics would be: > > a := operator.iadd(a, b) > Thinking about it more, I think the real stumper was what should happen for either of these: x = (a.b := 1) x = (a.b += 1) Take the first one and let's try to compile it to pseudo bytecode (which I'm making up on the spot but should be simple enough to understand if you've seen output from the "dis" module): LOAD 1 LOAD a SETATTR b ??? What do we do next? We could do LOAD a GETATTR b STORE x But this gives a's class the opportunity to change the value (because its __setattr__ could normalize the value, e.g. to a string or a float, and then its __getattribute__ would return the normalized value). But this seems a rare case and wastes time in the common case, and also seems somewhat more surprising than always assinging 1 to x regardless of what SETATTR did, so I'd rather forgo the extra GETATTR operation. So I think it should be LOAD 1 DUP LOAD a SETATTR b LOAD r1 STORE x I think the second example could be translated as follows (using a register rather than a sequence of DUPs and ROTs to save the extra copy of the result of the IADD that we want to store into x). LOAD a DUP GETATTR b LOAD 1 IADD COPY .r1 # copy into register r1 SETATTR b # this uses the reference to a that was left on the stack by DUP LOAD .r1 STORE x I used pen and paper to figure out what was on the stack at each point and had to rewrite the pseudo bytecode several times. But now I'm pretty sure this will pose no serious challenge for bytecode generation. But I'd like to point out to anyone who made it this far that this is not part of PEP 572! The PEP currently proposes neither "+=" in expressions nor targets that are attributes -- it only proposes "NAME := EXPR" because for the others the use cases are just too thin. (But in the past we said that about things like "(1, 2, *args, *more_args)" and eventually we found enough use cases for them that they were added. :-) -- --Guido van Rossum (python.org/~guido)
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com