lvalues and the lgb rule

Thomas Wouters thomas at xs4all.net
Sat Jul 7 05:38:35 EDT 2001


On Sat, Jul 07, 2001 at 01:33:56AM +0000, Eric Hagemann wrote:

> > Not dynamic.  Just look at the code in an editor:  if a name is bound
> > anywhere within a code block, and isn't declared in a "global" stmt, then
> > that name is local throughout the entire code block.

> Is this true ?

Yes.

> Given a file with the following

> print x
> x=1
> print x

> The first print will fail with a 'NameError'.  It was my (perhaps) wrong
> impression
> that x "came into being" at the assignment (x=1)

Yes and no. If you execute the above snippet at the top level (not inside a
function) you'll get a NameError because the name doesn't exist yet. This is
because you are evaluating in the 'global' namespace, and it is handled
slightly differently from the local namespace inside a function. If you
write the above as part of a function, say,

def spam():
    print x
    x = 1
    print x

spam()

You'll also get a NameError under 1.5.2, but a more appropriate
UnboundLocalError in newer versions of Python. The reason of the error is
the same in both cases, but the exact exception raised was changed to make
the difference between the first example and the second more obvious.
(UnboundLocalError is a subclass of NameError, so catching NameError will
still work for both cases.)

> I would think the variable is local to the code block once the assignement
> has been executed

No, it's local once the compiler sees an assignment statement for the
variable inside the code block. But because the global (module) namespace is
a global one as well as a local one, it behaves slightly differently there.
What happens is that the global namespace is a straight dictionary, where
assignment is a 'setitem', lookup is a 'getitem', and 'del' is a 'delitem'.

The local namespace inside a function is actually stored (in absence of
'exec' or 'import *') as a vector (list) and the names of all local
variables are translated into indexes. At runtime the interpreter will try
to retrieve the X'th element of the vector and notice it's empty (a NULL
value), raising the UnboundLocalError. A 'del' statement also empties the
element.

Just look at the LOAD_FAST opcode in Python/ceval.c in the source
distribution :)

-- 
Thomas Wouters <thomas at xs4all.net>

Hi! I'm a .signature virus! copy me into your .signature file to help me spread!




More information about the Python-list mailing list