Easy questions from a python beginner
Alf P. Steinbach /Usenet
alf.p.steinbach+usenet at gmail.com
Mon Jul 12 14:28:49 EDT 2010
* 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>
More information about the Python-list
mailing list