question on global variables

James J. Besemer jb at cascade-sys.com
Thu Oct 10 07:16:40 CEST 2002


mongo57a at comcast.net wrote:

>Somewhat new to Python here.....
>
>I want to change/use a value throughout my program - what I would normally
>refer to as a "global" variable.
>
>I see that there is a "global" command - and I assume its use would be
>global var_name. This I have coded (works) but I am unable to use it "global
>name var_name is not defined".
>
Your interpretation of "global" appears flawed.

You should re-read section 4.1 in the language manual about code blocks 
... and namespaces.

The "global" statement declares that variables which otherwise would be 
interpreted to be local are actually defined in an outer scope.

The key rule in Python is that names generally are "local" to whatever 
scope in which they are assigned a value.  This is what you want most of 
the time but occasionally leads to some subtle surprises.

    # "globals"
    count1 = count2 = 0

    def func1( n ):
        count1 = 0    # creates a new "local" count, distinct from 
global one
        count2 += n    # error: access local count2 before it is defined
        ...

    def func2( n ):
        global count1, count2    # causes next two statements to refer 
to above globals
        count1 = 0
        count2 += n

    class myobject:
        def func3( self, n ):
            global count2
            count1 = 0    # local
            count2 += n    # global count2, argument n
            self.count1    # a distinct instance variable

In the newer versions of Python, "nested scopes" are implemented.  This 
means that variables which are NOT assigned-to in a local scope are 
looked for in successively outer scopes.

def func3( n ):
    global count2            # necessary to make assigned-to local 
count2 global
    count2 += count1    # otherwise undefined count1 is found in global 
scope

Note that local scopes do NOT work in older versions of Python, in which 
case you also would have to expressly declare count1 as global in the 
above example.

Note that "global" is relative and generally means the outer most scope 
of a module.  Nevertheless, global names in imported modules generally 
are qualified by the module name.  E.g.,:

    import string
    string.join( alist )

Clear as mud?

Once you understand how they work, you should reconsider your need for 
globals.  In most cases, defining a class with one or more local names 
is a better solution.

E.g., instead of:

    count = 0

    def fn():
        global count
        ...
        count += n

you should define a class:

    class Counter:
        def __init__( self, init=0):
            self.count = init
        def inc( self, delta=1 ):
            self.count += delta

    counter = Counter()

    def fn():
        ...
        counter.inc( n )

Since the counter name is NOT assigned-to, under nested scope rules you 
don't have to declare it global.

In this stilted example, the overhead of the class seems excessive but 
in practice, you'll find it to be a vastly superior approach over the 
standard "rape and pilage" global style.

Regards

--jb


-- 
James J. Besemer		503-280-0838 voice
2727 NE Skidmore St.		503-280-0375 fax
Portland, Oregon 97211-6557	mailto:jb at cascade-sys.com
				http://cascade-sys.com	








More information about the Python-list mailing list