Antoon Pardon wrote: > > Now maybe I'm just not bright enough, so maybe you can explain what > something like col['t'] is evaluated to in a statement like: > > col['t'] = exp
In the notation given earlier, let us say that it would be this: namespace = col setitem(namespace, "t", exp) Note that in my notation I use the term namespace to apply to actual namespaces (locals, globals, classes, objects) as well as what I call "itemspaces" (things which store items). In the above, we still obtain the namespace first, but we don't attempt to fetch the item previously stored at item "t" (if any was present). [...] > Well maybe I'm missing your point entirely but would you be so friendly, > as to rephrase the following statements too: > > a = a + b This is where it gets interesting, even though it should not appear to do so. We might consider writing this as follows: setname(ns_target, "a", add(getname(ns_source, "a"), b)) Here, I've skipped over how b is obtained, but it'd be something like getname(locals, "b") or getname(globals, "b"). Since recent versions of Python perform some special tricks to disallow assignments involving mixed namespaces (considering a is global and that the above code is in a function), we probably can assume the same namespace is at work. But really, the most pertinent question relates to the evaluation of the namespaces themselves: a simple name binding operation involves the local or global namespaces which can be obtained without side-effects. Thus, the simple assignment above is mostly equivalent to the augmented assignment... a += b ...since ns_target == ns_source and their evaluation can be considered free of side-effects. In other words, we can rewrite it thus: assert ns_target == ns_source namespace = ns_target setname(namespace, "a", add(getname(namespace, "a"), b)) > a.b = a.b + c We could consider writing this: setattr(a, "b", add(getattr(a, "b"), c)) Once again, I've skipped over how c is obtained, since it isn't central to the assignment. As above, it appears that the namespace is the same on both sides of the assignment (given Python's assignment rules), although by using an opaque identifier the above example doesn't really permit us to illustrate this. We could expand the identifier a to investigate further: setattr(getname(ns_target, "a"), "b", add(getattr(getname(ns_source, "a"), "b"), c)) Which according to the above reduces to this: setattr(getname(namespace, "a"), "b", add(getattr(getname(namespace, "a"), "b"), c)) And to this: ns_a = getname(namespace, "a") setattr(ns_a, "b", add(getattr(ns_a, "b"), c)) Which shows that the augmented assignment is probably equivalent. See below for a better example. > a[b] = a[b] + c And again, we could consider writing this: setitem(a, b, add(getitem(a, b), c)) Once again, I've skipped over how b and c are obtained. Consider this as an exercise! ;-) And as noted above, the example doesn't really permit us to illustrate this point - you could expand the terms and produce something that suggests that this simple case is equivalent to an augmented assignment. > Because as far as I can see the rephrasing of these statements will > result in exactly the same results as their augmented assignment > counter parts. So following your logic above, we would have to > come to the conclusion that the "targets" of these statements are > evaluated once too. This while the language reference suggests > they are evaluated twice. Quoting from the reference: "In the augmented version, x is only evaluated once." Let us look in depth at some of the unillustrated issues from above. > IMO the language reference sugest that the stament: > > a[i] += [b] Here, we can be sure that the same namespace is involved: namespace = a setitem(namespace, i, add(getitem(namespace, i), [b])) > is more effective than: > > a[i] = a[i] + [b] Whilst I, knowing that a appears twice and believing that a always produces the same result, might write the same as above, let us consider a more complicated expression instead of a (where the function f returns a list): f()[i] = f()[i] + [b] Here, since we can make no guarantees that f() evaluates to the same thing every time it is called, we must evaluate it twice to honour the intent of the statement: setitem(f(), i, add(getitem(f(), i), [b] To see this clearly... f1 = f() f2 = f() setitem(f1, i, add(getitem(f2, i), [b]) Meanwhile, in the case of the augmented assignment... f()[i] += [b] ...the author has more or less stated that he/she wants f() to be evaluated only once - anything else would be surprising: namespace = f() setitem(namespace, i, add(getitem(namespace, i), b)) > IMO it suggests that the augmented assignment version is > just as effective as: > > a[i].append(b) > > Because, i hope, we agree that a[i] is evaluated only > once here! The rule is that if the namespace (what you call the primary, I think) is mentioned once, it is evaluated only once. [...] > Yes, and what you are doing here is eliminating the double evaluation > of the primary. In a statement like a.f().x = ... the a.f() part > is the primary according to the assignment reference. Indeed. The language reference uses very simple opaque identifiers to supposedly illustrate its point but, as we saw above, such examples actually obstruct the path to understanding. That a simple identifier x obtained from some namespace is not evaluated twice is almost tangential to understanding the principles involved. Paul -- http://mail.python.org/mailman/listinfo/python-list