[Python-Dev] more timely detection of unbound locals

Isaac Morland ijmorlan at uwaterloo.ca
Mon May 9 15:26:38 CEST 2011


On Mon, 9 May 2011, Eli Bendersky wrote:

> It's a known Python gotcha (*) that the following code:
>
> x = 5
> def foo():
>    print(x)
>    x = 1
>    print(x)
> foo()
>
> Will throw:
>
>       UnboundLocalError: local variable 'x' referenced before assignment
>
> On the usage of 'x' in the *first* print. Recently, while reading the
> zillionth question on StackOverflow on some variation of this case, I
> started thinking whether this behavior is desired or just an implementation
> artifact.
>
> IIUC, the reason it behaves this way is that the symbol table logic goes
> over the code before the code generation runs, sees the assignment 'x = 1`
> and marks 'x' as local in foo. Then, the code generator generates LOAD_FAST
> for all loads of  'x' in 'foo', even though 'x' is actually bound locally
> after the first print. When the bytecode is run, since it's LOAD_FAST and no
> store was made into the local 'x', ceval.c then throws the exception.
>
> On first sight, it's possible to signal that 'x' truly becomes local only
> after it's bound in the scope (and before that LOAD_NAME can be generated
> for it instead of LOAD_FAST). To do this, some modifications to the symbol
> table creation and usage are required, because we can no longer say "x is
> local in this block", but rather should attach scope information to each
> instance of "x". This has some overhead, but it's only at the compilation
> stage so it shouldn't have a real effect on the runtime of Python code. This
> is also less convenient and "clean" than the current approach - this is why
> I'm wondering whether the behavior is an artifact of the implementation.

x = 5
def foo ():
 	print (x)
 	if bar ():
 		x = 1
 	print (x)

Isaac Morland			CSCF Web Guru
DC 2554C, x36650		WWW Software Specialist


More information about the Python-Dev mailing list