* Steven D'Aprano, on 12.07.2010 04:39:
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.
Yes.
What I disproved was the statement that every Python variable is created by the
execution of an assignment.
Some (the global ones) are. :-)
It seems to me that "a slot to hold the variable is created for local
variables" is an implementation detail, not a language feature.
Yes.
However, any Python implementation has to implement the same user level
semantics in some way (note: use level semantics do not include "space reserved"
for an unassigned variable, or even for all assigned variables since with single
assignment a sufficiently smart compiler can optimize away the space, but user
level semantics do include existence and resultant effect).
As I see it it doesn't matter whether the implementation is CPython call frame
slots or that mechanism called something else or a different mechanism called
the same or a different mechanism called something different; what IMO matters
is same semantics, that any assignment to a variable within a routine serves as
a compile time declaration, creating that local variable in advance, unless,
with Python 3.x., that name has been declared as a 'global' or 'nonlocal'.
So, this is a possible point of disagreement.
I say the semantics of local variable creation are part of the language
definition, but I get the /impression/ that maybe you think it's
CPython-specific, that e.g.
def foo():
x
x = 0
might not raise an unassigned variable exception with some conforming Python
implementation, i.e. different effect for same code with different
implementations, that this is at least /unspecified behavior/ in Python?
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.
He he. I wouldn't say "space reserved". That is an implementation detail.
Cheers,
- Alf
--
blog at <url: http://alfps.wordpress.com>
--
http://mail.python.org/mailman/listinfo/python-list