global variable confusion

rdmurray at bitdance.com rdmurray at bitdance.com
Tue Feb 3 20:25:05 EST 2009


"Robert D.M. Smith" <robert.dm.smith at gmail.com> wrote:
> I have a question on global variables and how to use them.  I have 2 files;
> a.py & b.py
> 
> # a.py -----
> 
> myvar = { 'test' : '123' }
> 
> # -------
> # b.py -----
> 
> from a import myvar
> 
> def test():
>      a.myvar = { 'blah' : '456' }
> 
> # -----
> 
> If I *'import a*' & type *'a.myvar'* it prints 'test' & '123'.
> 
> Now, if I *'import b'* & type *'b.test()'* ... does this actually change the
> contents of myvar? It seems I have to do *'print b.myvar'* to see the change
> but really I want to just simply do* 'print myvar'*. I want to be able to
> change myvar anywhere. Please help me grasp this concept.

As someone else told you the code above won't work, because you haven't
imported the 'a' that your 'test' function references.  But let's
ignore that issue.

I'm guessing the confusion you are experiencing is arising from the 
concept of name spaces (a very powerful and ubiquitous concept in Python).
A namespace maps an identifier to a object.  A given identifier exists in
exactly one namespace, but many identifiers can refer to the same object.

When you do 'from a import myvar', you are setting the identifier 'myvar' 
_in the current model's global namespace_ to point to the same object that
'myvar' does in module a.  If, in the current module, you then do, say,
'myvar = 1', what you've done is _rebound_ the identifier 'myvar' in the
current module's global namespace to the integer 1 (an integer object).
You haven't affected anything in module 'a'.

If, on the other hand, you do 'import a', what you've done is bound the
global namespace of module 'a' (an object) to the identifier 'a' in the
current module's global namespace.  If you were to do 'a = 1' in the
current module, then you'd rebind the identifier 'a' to the integer 1.
After that a.myvar would be an error.

If, however, you say 'a.myvar = 1', what you've done is rebound the
identifier 'myvar' _in module a's global namespace_ to the integer 1.  
Anything that subsequently references a.myvar is going to get '1' as
the result.

Now, to take your brain around the final bend, think about what happens 
if one module does 'from a import myvar', and module imported later does 
'import a; a.myvar = 1'.  The first module bound its global identifier
'myvar' to the object a.myvar originally pointed to (a little dictionary
in your example above).  The second module rebinds the identifier myvar in 
module a's global namespace to the integer 1.  But that doesn't affect
the first module's global namespace.  There, the identifier 'myvar'
is still bound _to the original dictionary_.

A modification of your example should make what is going on clearer:

    ---------------------------
    # a.py
    myvar = {'test': '123'}
    ---------------------------
    # b.py
    from a import myvar
    myvar['test'] = '456'
    ---------------------------

    Python 2.6.1 (r261:67515, Jan  7 2009, 17:09:13)
    [GCC 4.3.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from a import myvar
    >>> print myvar
    {'test': '123'}
    >>> import b
    >>> print myvar
    {'test': '456'}

The difference between the above and doing 'myvar = 1' is that in the
above code the statement 'myvar['test'] = '456' modifies _the object
that myvar points to_, while 'myvar = 1' modifies _what_ myvar points to.

Study that last sentence until you understand it, and a lot of things
that happen in Python will be much clearer to you (such as what
happens when you pass arguments to a function or method!)

If what I have written doesn't make sense, feel free to ask more 
questions.

--RDM




More information about the Python-list mailing list