problem with exec and locals()
Mel
mwilson at the-wire.com
Tue Jul 1 09:15:27 EDT 2008
rocksportrocker wrote:
>
> 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:
>>> dis.dis (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
>>> dis.dis(test2)
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.
More information about the Python-list
mailing list