[Tutor] Scoping question
Gonçalo Rodrigues
op73418@mail.telepac.pt
Mon, 9 Sep 2002 18:00:48 +0100
----- Original Message -----
From: "Dana Larose" <dana@pixelenvy.ca>
To: <tutor@python.org>
Sent: Monday, September 09, 2002 4:27 PM
Subject: [Tutor] Scoping question
> Hello,
Hello
>
> (Hope this is the right mailing list for this question!)
>
It is.
> I've been using Python for several months now, and I've run across a
> scoping issue involving global variables. Consider this program scrap:
>
> blah = 0
> list = [0]
>
> def foo():
> blah += 1
>
> def bar():
> list[0] += 1
>
> Now, bar would compile and execute fine, but foo is illegal because:
>
> 'UnboundLocalError: local variable 'blah' referenced before assignment'
>
> Now, I'll guess that my problem is that Python is treating blah as though
> it were local and the assignment fails because the variable hasn't been
> created yet. But why doesn't Python search up the scoping chain when the
> local assignment fails? Also, if foo had been defined as just being:
>
> def foo():
> print blah
>
> It executes just fine and can find blah. Why can it find the global in
> this context but not the other?
>
> And finally, why does the assignment to a list element execute
> successfully?
>
> Dana.
> dana@pixelenvy.ca
>
The problem is the difference between local variables and global ones.
Consider the scrap
>>> blah = 1
>>> def foo():
... print blah
...
>>> foo()
1
Here Python knows that I wanted to acess the global blah because blah is a
free name inside foo (i.e. there is no assignment to it). Now consider
>>> def foo2():
... blah = 2
... print blah
...
>>> foo2()
2
>>> print blah
1
Here Python has created a *local* blah inside foo, which, when foo is done,
is discarded - and that is why print blah gives the global blah, e.g. 1. Now
consider
>>> def foo3():
... blah += 1
...
>>> foo3()
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
File "<interactive input>", line 2, in foo3
UnboundLocalError: local variable 'blah' referenced before assignment
According to the first case, the name blah is local and you are rebinding
it. But blah += 1 is a shortcut for
blah = blah + 1
so you are trying to acess something that it is not defined.
*IF* you want to acess the global blah inside foo you have to explicitly
order Python to do so, e.g.
>>> def foo4():
... global blah
... blah += 1
...
>>> foo4()
>>> print blah
2
Hope it helps,
Gonçalo Rodrigues