rocksportrocker said:
Hi,
the following code does not work until I ommit the "a=0" statement.
def test():
exec "a=3" in locals()
print a
a=0
test()
print raises:
UnboundLocalError: local variable 'a' referenced before
assignment
Can anybody explain what is going wrong here ?
AFAIK, local variables are implemented rather like __slots__ in new-style
classes. This is a very valuable efficiency measure, but it can cause this
kind of trouble. Without `a=0`, the bytecode compiler makes no slot for a,
and dis.dis shows the following bytecode for test: 2 0 LOAD_CONST 1 ('a=3')
3 LOAD_NAME 0 (locals)
6 CALL_FUNCTION 0
9 DUP_TOP
10 EXEC_STMT
3 11 LOAD_NAME 1 (a)
14 PRINT_ITEM
15 PRINT_NEWLINE
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
At address 11, LOAD_NAME 1(a) gets the value that was set by exec.
With a=0, the code is 2 0 LOAD_CONST 1 ('a=4')
3 LOAD_NAME 0 (locals)
6 CALL_FUNCTION 0
9 DUP_TOP
10 EXEC_STMT
3 11 LOAD_FAST 0 (a)
14 PRINT_ITEM
15 PRINT_NEWLINE
4 16 LOAD_CONST 2 (0)
19 STORE_FAST 0 (a)
22 LOAD_CONST 0 (None)
25 RETURN_VALUE
and here, the value of a is found in slot 0 via LOAD_FAST. Slot 0 is used
because a=0 forced a to be a local variable.
Apparently, exec in locals() knows nothing about slots (because locals() is
the only dictionary in the universe where slots would be involved ? --
perhaps not, but close).
Mel.