[Python-ideas] Why does += trigger UnboundLocalError?
Terry Reedy
tjreedy at udel.edu
Thu Jun 2 00:42:03 CEST 2011
On 6/1/2011 1:32 PM, Bruce Leban wrote:
> >>> def f(x,y):
> x += y
> >>> dis.dis(f)
> 2 0 LOAD_FAST 0 (x)
> 3 LOAD_FAST 1 (y)
> 6 *INPLACE_ADD*
> 7 STORE_FAST 0 (x)
> 10 LOAD_CONST 0 (None)
> 13 RETURN_VALUE
> >>> def g(x,y):
> x = x + y
>
> >>> dis.dis(g)
> 2 0 LOAD_FAST 0 (x)
> 3 LOAD_FAST 1 (y)
> 6 *BINARY_ADD*
> 7 STORE_FAST 0 (x)
> 10 LOAD_CONST 0 (None)
> 13 RETURN_VALUE
(In 3.2, one no longer needs to wrap code in a function to dis it.
see below.)
To see the 'calculate the source/target just once instead of twice'
part, you need a source/target that actually requires calculation.
>>> from dis import dis
>>> dis('x[i] = x[i] + 1')
1 0 LOAD_NAME 0 (x)
3 LOAD_NAME 1 (i)
6 BINARY_SUBSCR
7 LOAD_CONST 0 (1)
10 BINARY_ADD
11 LOAD_NAME 0 (x)
14 LOAD_NAME 1 (i)
17 STORE_SUBSCR
18 LOAD_CONST 1 (None)
21 RETURN_VALUE
>>> dis('x[i] += 1')
1 0 LOAD_NAME 0 (x)
3 LOAD_NAME 1 (i)
6 DUP_TOP_TWO
7 BINARY_SUBSCR
8 LOAD_CONST 0 (1)
11 INPLACE_ADD
12 ROT_THREE
13 STORE_SUBSCR
14 LOAD_CONST 1 (None)
17 RETURN_VALUE
Even this does not show much difference as the dup and rotate substitute
for two loads but do not actually save any calculation. However,
>>> dis('a.b[c+d] = a.b[c+d] + 1')
1 0 LOAD_NAME 0 (a)
3 LOAD_ATTR 1 (b)
6 LOAD_NAME 2 (c)
9 LOAD_NAME 3 (d)
12 BINARY_ADD
13 BINARY_SUBSCR
14 LOAD_CONST 0 (1)
17 BINARY_ADD
18 LOAD_NAME 0 (a)
21 LOAD_ATTR 1 (b)
24 LOAD_NAME 2 (c)
27 LOAD_NAME 3 (d)
30 BINARY_ADD
31 STORE_SUBSCR
32 LOAD_CONST 1 (None)
35 RETURN_VALUE
>>> dis('a.b[c+d] += 1')
1 0 LOAD_NAME 0 (a)
3 LOAD_ATTR 1 (b)
6 LOAD_NAME 2 (c)
9 LOAD_NAME 3 (d)
12 BINARY_ADD
13 DUP_TOP_TWO
14 BINARY_SUBSCR
15 LOAD_CONST 0 (1)
18 INPLACE_ADD
19 ROT_THREE
20 STORE_SUBSCR
21 LOAD_CONST 1 (None)
24 RETURN_VALUE
The latter has the same dup-rotate in place of a bit more calculation.
The same would be true of, for instance, f(a).b.
--
Terry Jan Reedy
More information about the Python-ideas
mailing list