"Tim Roberts" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] | Marc 'BlackJack' Rintsch <[EMAIL PROTECTED]> wrote: | | >On Fri, 22 Feb 2008 11:00:17 -0800, Aahz wrote: | > | >> It's just too convenient to be able to write | >> | >> L += ['foo'] | >> | >> without rebinding L. | > | ><nitpick>But ``+=`` does rebind.</nitpick> | | Usually, but there's an exception for lists, which a specific | implementation for += that calls "append". Or do I misunderstand you?
There is no exception at the compiler level, and indeed, cannot be, because in general, the compiler *does not know* the types of either target or augment. target += augment is compiled, in effect, as compute target and load target_object compute and load augment_object call target_object.__iadd__(augment_object) store return_object at target In the list case, the rebinding is to the *same* object! -- because list.__iadd(l1,l2)__ returns l1 extended with l2 rather than a new list l1+l2, as the specification allows. Augmented (inplace) assignment is still assignment (binding). | C:\tmp>python | Python 2.4.4 (#71, Oct 18 2006, 08:34:43) [MSC v.1310 32 bit (Intel)] on | win32 | Type "help", "copyright", "credits" or "license" for more information. | >>> L = [1,2,3] | >>> id(L) | 10351000 | >>> L += [4] | >>> id(L) | 10351000 L has been rebound to the same object, hence same id. Unfortunately, such rebinding is only visible (that I can think of) when it fails: >>> t=([],) >>> t[0]+=[1] Traceback (most recent call last): File "<pyshell#8>", line 1, in -toplevel- t[0]+=[1] TypeError: object does not support item assignment >>> t ([1],) The list comprising t[0] is extended by its __iadd__ method. The exception arises due to the subsequent attempted rebinding to t[0] (see dis output below), which is, of course, not permissible. >>> t[0].extend([2]) >>> t ([1, 2],) Extension without attempted illegal rebinding raises no error. CPython specifics: >>> from dis import dis >>> def fi(i): i+=1; return i >>> dis(fi) 1 0 LOAD_FAST 0 (i) 3 LOAD_CONST 1 (1) 6 INPLACE_ADD 7 STORE_FAST 0 (i) 10 LOAD_FAST 0 (i) 13 RETURN_VALUE >>> def fl(l): l += [1]; return l >>> dis(fl) 1 0 LOAD_FAST 0 (l) 3 LOAD_CONST 1 (1) 6 BUILD_LIST 1 9 INPLACE_ADD 10 STORE_FAST 0 (l) 13 LOAD_FAST 0 (l) 16 RETURN_VALUE Treating the VM stack as a Python list, INPLACE_ADD executes something like stack[-2] = stack[-2].__iadd__(stack[-1]) stack.pop() # leaving returned object on top of stack Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list