Augument assignment versus regular assignment

Paul Boddie paul at boddie.org.uk
Mon Jul 17 05:12:49 EDT 2006


Antoon Pardon wrote:
>
> What the language reference should have said IMO is that in case x
> is an attribute reference, index or slicing, the primary expression
> will be evaluated only once, as will be the index or slice in the
> two latter cases.

I think the difficulty here for the author of this particular section
of the reference is in describing the mechanisms at work whilst keeping
the description at a conceptual level which can be directly connected
to the source text in a program. However, apart from providing a vague
intuition about how augmented assignment must work, the description
doesn't answer all questions effectively, particularly in cases where
the actual assignments are not simple local/global name binding
operations.

One way to consider augmented assignment is as a statement formulated
in the following way:

setvalue(namespace, name, op(getvalue(namespace, name), expr))

Consider an augmented assignment on a local name:

a += b

This could be phrased as follows:

setname(locals, "a", add(getname(locals, "a"), b))

Or really:

setname(locals, "a", add(getname(locals, "a"), getname(locals, "b")))

Consider an augmented assignment on an attribute:

a.b += c

This could also be phrased similarly:

setattr(a, "b", add(getattr(a, "b"), c))

And consider an augmented assignment on an item:

a[b] += c

This too is phrased similarly:

setitem(a, b, add(getitem(a, b), c))

So, as long as you're willing to accept that the setvalue class of
operations (setname, setattr, setitem) aren't really evaluating the
target of the assignment - strictly, the thing being replaced in the
assignment - then only the getvalue class of operations (getname,
getattr, getitem) are causing the evaluation of the target. And since
setname is just a normal name binding assignment which we know doesn't
cause the target to be evaluated, we can assume that the other
operations in that class behave similarly.

Now, one aspect of evaluation has been skipped in the above
explanation: what if we have a "complicated" expression on the left
hand side? Consider this:

a.f().x += y

We could naively write this as follows:

setattr(a.f(), "x", add(getattr(a.f(), "x"), y))

However, it looks like we are evaluating at least part of the left hand
side twice. Thus, we need to be a bit clearer about what really
happens:

namespace = a.f()
setattr(namespace, "x", add(getattr(namespace, "x"), y))

In order to avoid double evaluation, we first obtain the target
namespace (or itemspace, I suppose). Then, we perform the operations as
stated above.

So, to conclude, augmented assignment involves the evaluation of any
expression which gives the target namespace (trivial in the case of
local/global name binding, non-trivial otherwise), then a compound
operation of the form given above involving two classes of operations,
each providing operations to act on names, attributes and items.

I doubt that this explanation is simple, clear or efficient enough for
the language reference, but then any explanation shouldn't be
constrained in terms of complexity in a way that, for example, a
tutorial explanation should be. Despite cries of "you must get it now!"
from various quarters, I think this thread has been informative, and
I'd like to thank you for bringing this matter to the group's
attention, Antoon.

Paul




More information about the Python-list mailing list