[Tutor] "Forward" declarations

Daniel Yoo dyoo@hkn.EECS.Berkeley.EDU
Fri, 18 Aug 2000 02:53:40 -0700 (PDT)


On Fri, 18 Aug 2000, Danie Roux wrote:

> How do I use a variable that is only declared later on in the file? Is
> global what I'm looking for? 
> 
> My question then is does 'global' make the variable global within the
> module or across the whole program?

Yes, when you use the global statement, it tells Python to treat that
variable as a global.  There's a weird reason why it's necessary.  It's a
little hard to explain without seeing it.  Here's code that demonstrates
the problem (I'll be changing function() in these examples a lot.):


###
g = "This is a global variable"

def function():
    print g
    g = "I will cause trouble!"
    print g


if __name__ == '__main__':
    function()
    print g
###

Looks coy and innocent, but here's what happens when you try to run it:

###
[dyoo@einfall python]$ python trickyscope.py
Traceback (innermost last):
  File "trickyscope.py", line 10, in ?
    function()
  File "trickyscope.py", line 4, in function
    print g
NameError: g
###

What happens is that when a function gets defined, Python performs a quick
scan through to see which variables are local.  In a function, if you do
any assignments to a variable, it's a local variable.

Because it sees the 'g = "I will cause trouble!"', it will assume that g
is locally defined, and treats it as such.  That's why we see that error
message later, when it actually tries to resolve what g is within
function().

If you want it to treat g as the global, then you'll need to use the
global statement to inform Python to override the default rules:

###
def function():
    global g
    print g
    g = "I will cause trouble!"
    print g
###

Then things will work as expected:

###
[dyoo@einfall python]$ python trickyscope.py
This is a global variable
I will cause trouble!
I will cause trouble!
###



Next, if you had initially put:

###
def function():
    g = "I will cause trouble!"
    print g
###

Here's what happens:

###
[dyoo@einfall python]$ python trickyscope.py
I will cause trouble!
This is a global variable
###

This is because of the assignment --- it'll treat g as local inside
function().  So the global isn't affected, as we see when we come out of
function().



Now, here's the kicker:

###
def function():
    print g
###

###
[dyoo@einfall python]$ python trickyscope.py
This is a global variable
This is a global variable
###

No assignment == g stays global.  Is this evil or what?  *grin*


These weird situations are rare, to say the least.  In any case, you
should avoid reusing the name of a global anyway.  I usually use globals
as constants; I never reassign them.  Because of that, I've never run into
this situation in real code.

Most likely, as long as you're not abusing global variables, you'll be
ok.  It is good to be aware of this; it's perverse, but it makes sense if
you construct a model of what's happening.

Good luck!