[Python-ideas] Unpacking iterables for augmented assignment

James Lu jamtlu at gmail.com
Sun Aug 26 21:23:41 EDT 2018


Hi Johnathan

I echo your points. Indeed, the PEP referenced to refers to a "tuple
expression" in the grammatical and not the programmatic sense.

Finally, here's something that surprised me a little bit

>>> x = [1, 2]; id(x)
140161160364616
>>> x += [3, 4]; id(x)
140161160364616

>>> x = (1, 2); id(x)
140161159928520
>>> x += (3, 4); id(x)
140161225906440

Notice that '+=' creates uses the same object when the object is
a
list, but creates a new object. This raises the question: Why and
how
does Python behave in this way?

It's because lists are mutable are tuples are immutable.
There's a dunder iadd method and a dunder add method.
iadd magic methods, operating on the left hand side, return None and
modify the object in-place. add magic methods return the result and
don't modify the object it's called on.
iadd is mutable add, whereas add is "return a copy with the result
added"

>>> tuple.__iadd__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'tuple' has no attribute '__iadd__'
type object 'tuple' has no attribute '__iadd__'
>>> tuple.__add__
<slot wrapper '__add__' of 'tuple' objects>
>>> list.__iadd__
<slot wrapper '__iadd__' of 'list' objects>
>>> list.__add__
<slot wrapper '__add__' of 'list' objects>


tuple1 = tuple1.__add__(tuple2)

list1.__iadd__(list2)

> Does it IN PRACTICE bring sufficient benefits to users?

I found myself needing this when I was writing a monte-carlo
simulation in python that required incrementing a tallying counter
from a subroutine.

Not sure where the rest of your message was going; it mostly just
> seemed to repeat examples from earlier posts?
>
Yes, I just wanted to summarize the existing discussion.




On Sun, Aug 26, 2018 at 1:52 PM Tim Peters <tim.peters at gmail.com> wrote:

> [James Lu]
> > > Currently, is <expr1> = <expr2> = <expr3> = <expr4> always equivalent
> > > to <expr1> = <expr4>; <expr2> = <expr4>; <expr3> = <expr4>?
>
> [Stephen J. Turnbull[
> > No.  It's equivalent to
> >
> >     <expr3> = <expr4>
> >     <expr2> = <expr3>
> >     <expr1> = <expr2>
> >
> > and the order matters because the <expr>s may have side effects.
>
> This is tricky stuff.  In fact the rightmost expression is evaluated once,
> and then the bindings are done left-to-right using the result of evaluating
> the rightmost expression.  Like so:
>
> >>> def return2():
> ...     print("called return2")
> ...     return 2
> >>> xs = [10, 20, 30, 40]
> >>> i = xs[i] = return2()
> called return2
> >>> xs
> [10, 20, 2, 40]
> >>> i
> 2
>
> So James's account is closer to what's done, but is missing weasel words
> to make clear that <expr4> is evaluated only once.
>
> Sane code doesn't rely on "left to right", but may well rely on "evaluated
> only once".
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180826/37fa4e61/attachment.html>


More information about the Python-ideas mailing list