Easy questions from a python beginner

Steven D'Aprano steve-REMOVE-THIS at cybersource.com.au
Sun Jul 11 22:39:39 EDT 2010


On Mon, 12 Jul 2010 03:12:10 +0200, Alf P. Steinbach /Usenet wrote:

> * MRAB, on 12.07.2010 00:37:
[...]
>> In Java a variable is declared and exists even before the first
>> assignment to it. In Python a 'variable' isn't declared and won't exist
>> until the first 'assignment' to it.
> 
> That is a misconception.
> 
> In Python a variable is declared by having an assignment to it, which
> for a local variable may be anywhere within a routine.

Oh, I'm going to regret being sucked into this... 

In *CPython*, but not necessarily other implementations, variables which 
are local to a function are not kept in a dictionary-based namespace, but 
in slots in the code object (not to be confused with __slots__ used for 
classes). Python has STORE_FAST and LOAD_FAST byte-codes for accessing 
locals.

This is intended as a speed, and possibly memory, optimization. I don't 
believe this is a requirement though, so implementations may not do this.

It is true that the slot is created at compile time, and in *that sense*, 
local variables exist before they are bound. I'm not entirely convinced 
that this is the only sense that matters, but never mind. The error 
message given exposes this to the user:

>>> def f():
...     print x
...     x = 1
...
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
UnboundLocalError: local variable 'x' referenced before assignment


If you try this with a global, you get this:

>>> def f():
...     global x
...     print x
...
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in f
NameError: global name 'x' is not defined

In this case, there's no doubt that global variable "x" doesn't exist at 
all -- there is no key "x" in the global namespace.


It seems to me that "a slot to hold the variable is created for local 
variables" is an implementation detail, not a language feature. CPython 
could easily hide the difference by changing the exception from 
UnboundLocalError to:

NameError: local name 'x' does not exist

and nobody would be any wiser. (Well, perhaps people who catch 
UnboundLocalError, but why would you do that?)

I also note that UnboundLocalError is a subclass of NameError, so 
"variable exists but is not bound" is considered to be a special case of 
"variable doesn't exist" rather than a completely independent case. In 
that sense, I think I'm on solid ground to say that in Python variables 
don't exist until they are bound to a value, and leave it to pedants like 
you and I to mention that for CPython local variables have space reserved 
for them by the compiler before they are bound.



-- 
Steven



More information about the Python-list mailing list