On 2006-07-10, Jim Segrave <[EMAIL PROTECTED]> wrote: > In article <[EMAIL PROTECTED]>, > Antoon Pardon <[EMAIL PROTECTED]> wrote: >>On 2006-07-09, Fredrik Lundh <[EMAIL PROTECTED]> wrote: >>> Frank Millman wrote: >>> >>>> So it looks as if x += [] modifies the list in place, while x = x + [] >>>> creates a new list. >>> >>> objects can override the += operator (by defining the __iadd__ method), >>> and the list type maps __iadd__ to extend. other containers may treat >>> += differently, but in-place behaviour is recommended by the language >>> reference: >>> >>> An augmented assignment expression like x += 1 can be rewritten as >>> x = x + 1 to achieve a similar, but not exactly equal effect. In >>> the augmented version, x is only evaluated once. Also, when possible, >>> the actual operation is performed in-place, meaning that rather than >>> creating a new object and assigning that to the target, the old object >>> is modified instead. >> >>What does it mean that x is only evaluated once. I have an avltree module, >>with an interface much like a directory. So I added print statements to >>__setitem__ and __getitem__ and then tried the following code. >> >>>>> from avltree import Tree >>>>> t=Tree() >>>>> t['a'] = 1 >>__setitem__, key = a >>>>> t['a'] >>__getitem__, key = a >>1 >>>>> t['a'] = t['a'] + 1 >>__getitem__, key = a >>__setitem__, key = a >>>>> t['a'] += 1 >>__getitem__, key = a >>__setitem__, key = a >>>>> t['b'] = [] >>__setitem__, key = b >>>>> t['b'] = t['b'] + [1] >>__getitem__, key = b >>__setitem__, key = b >>>>> t['b'] += [2] >>__getitem__, key = b >>__setitem__, key = b >> >>So to me it seems that when we substitute t['a'] or t['b'] for x, >>x is evaluated twice with the augmented version, just like it >>is with the not augmented version. > > $ cat x.py > > def getindex(ind = 0): > print 'getindex() called' > return ind > > a = [0, 1, 2, 3, 4, 5] > a[getindex(0)] = a[getindex(0)] + 17 > print a > a[getindex(1)] += 22 > print a > > $ python x.py > getindex() called > getindex() called > [17, 1, 2, 3, 4, 5] > getindex() called > [17, 23, 2, 3, 4, 5] > > In this case, getindex() is a rather pointless function, but it could > be an expensive one or one with side effects or even one which alters > state, so that it gives different values on subsequent calls with the > same argument. > > The += version finds the object to be operated upon once, the expanded > version does it twice.
I disagree. The += version only evaluates the index once, but still has to find the object twice. Let us start with the following: t['b'] = [] Now with x being evaluated once, I would expect that t[getindex('b')] += [1] would be equivallent to: _key = getindex('b') _lst = t[_key] _lst += [1] And not to the following: _key = getindex('b') _lst = t[_key] _lst += [1] t[_key] = _lst But as far as I can interpret what is happening from the printed lines the second is happening and not the first. So in this example some optimisation has happened, by calculating the key only once, but the search for the object using that precalculated key happens twice, once with __getitem__ and once with __setitem__. >>> t['b'] = [] __setitem__, key = b >>> t[getindex('b')] += [1] getindex() called __getitem__, key = b __setitem__, key = b -- Antoon Pardon -- http://mail.python.org/mailman/listinfo/python-list