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
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to