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