On Dec 26, 1:08 am, Steven D'Aprano <[EMAIL PROTECTED] cybersource.com.au> wrote: > On Mon, 24 Dec 2007 18:01:53 -0800, Raymond Hettinger wrote: [...] > > The first succeeds and the second fails. > > And this is a good idea? > > Shouldn't the tuple assignment raise the exception BEFORE calling > __iadd__ on the item, instead of after?
If you look at the bytecode generated, this doesn't seem possible: >>> def f(): ... a = ([1],) ... a[0] += [2] ... >>> import dis >>> dis.dis(f) 2 0 LOAD_CONST 1 (1) 3 BUILD_LIST 1 6 BUILD_TUPLE 1 9 STORE_FAST 0 (a) 3 12 LOAD_FAST 0 (a) 15 LOAD_CONST 2 (0) 18 DUP_TOPX 2 21 BINARY_SUBSCR 22 LOAD_CONST 3 (2) 25 BUILD_LIST 1 28 INPLACE_ADD 29 ROT_THREE 30 STORE_SUBSCR 31 LOAD_CONST 0 (None) 34 RETURN_VALUE BINARY_SUBSCR puts a[0] on the stack, it has no way to know that a[0] will be changed in place. To allow an exception to be thrown before the in-place modification of a[0], there should be a new bytecode instruction, say BINARY_SUBSCR_WITH_A_VIEW_TO_CHANGE_IN_PLACE, which checks that the subscriptable object supports STORE_SUBSCR (;-). [...] > I was never a big fan of augmented assignments. I think it goes against > the Python grain: it's an implied operation, using punctuation, for the > sole (?) benefit of saving a keystroke or three. > > But I think this behaviour counts as a wart on the language, rather than > a bug. Yes. I didn't realise this before you mentioned it, but the culprit here seems to be the augmented assignment which acts differently on mutable and immutable objects: b = a # say a is immutable a += c # equivalent to a = a + c b is a # -> False b = a # Now say a is mutable a += c # equivalent to a.__iadd__(c) b is a # -> True OTOH augmented assignent are a slight optimisation: a[i] += 1 will look for the value of a and i only once and duplicate them on the stack, whereas a[i] = a[i] + 1 will need to resolve a and i twice (which can be costly if a and i are globals) -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list