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 -- http://mail.python.org/mailman/listinfo/python-list