[Python-Dev] behavior of inplace operations

David Abrahams David Abrahams" <david.abrahams@rcn.com
Mon, 17 Jun 2002 07:44:16 -0400


From: "Tim Peters" <tim.one@comcast.net>


> [David Abrahams]
> > ...
> > The pathological/non-generic cases are> the ones that make me think
twice
> > about using the inplace ops at all. They don't, in fact, "just work",
so
> > I have to think carefully about what's happening to avoid getting
myself
> > in trouble.
>
> I didn't understand this thread.  The inplace ops in Python do "just
work"
> to my eyes, but I expect them to work the way Python defines them to
work,
> which is quite uniform.  For example,
>
>     e1[e2] += e3
>
> acts like
>
>     t0, t1 = e1, e2
>     t0[t1] = t0[t1] + e3

But that's not even right, AFAICT. Instead, its:

    t0, t1 = e1, e2
    t2 = t0[t1]
    t2 += e3        # possible rebinding operation
    t0[t1] = t2

> There's no guarantee that e1[e2] as a whole is evaluated at most once

Actually, that was exactly what I expected. What I didn't expect was that
there's a guarantee that it's evaluated twice, once as part of a getitem
and once as part of a setitem.

> The way an augmented assignment in Python works is defined by cases, on
the
> form of the target.  Those were the "subscription" and "attributeref"
forms
> of target.  There are two other relevant forms of target, "identifier"
and
> "slicing", and they're wholly analogous.  Note an implication:  in a
> "complicated" target, it's only the top-level subscription or attribute
> lookup that gets evaluated twice; e.g.,
>
>     e1[e2].e3[e4] += e5
>
> acts like
>
>     t0, t1 = e1[e2].e3, e4
>     t0[t1] = t0[t1] + e5

I understood that part, but thanks for going to the trouble.

> Note that Python doesn't have a reference-to-lvalue concept.

Never expected it to.

> If you don't
> believe "but it should, so I'm going to think as if it does", there's
> nothing surprising about augmented assignment in Python.

I don't think it should have a reference-to-lvalue. Please, give me a tiny
bit of credit for being able to think Pythonically. I don't see everything
in terms of C++; I just expected Python not to do a potentially expensive
lookup and writeback in the cases where it could be avoided. Other people,
apparently, are also surprised by some of the cases that arise due to the
unconditional write-back operation.

> Indeed, I'm not
> even surprised by what this prints <wink>:
>
> >>> a = range(12)
> >>> a[2:9] += [666]
> >>> a

I guess I am, even if I believed your "as-if" description:

>>> a = range(12)
>>> t0,t1 = a,slice(2,9)
>>> t0[t1] = t0[t1] + [666]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: sequence index must be integer

can-we-stop-beating-this-horse-now-ly y'rs,
dave