Assignments and globals

David Bolen db3l at fitlinxx.com
Fri Aug 18 04:16:27 EDT 2000


echuck3 at my-deja.com writes:

> Here's a very distilled version of my problem:
> 
> settings = { 'x': {},  'y': {} }
> class K:
>     def foo(self):
>         settings = settings['x']
> K().foo()
> 
> I get "Name error: settings" on this. If I change the line to:
>         s = settings['x']
> 
> Then everything works. It appears that in the statement 'a = b', Python
> starts mucking with the namespace before b is evaluated.

Actually, it's for an entirely different reason.  Because Python
(during compilation) sees you make an assignment to the name
'settings', it declares settings as a local variable for that entire
scope.  Thus, the NameError you are getting really is on the
"settings['x']" portion of the code (e.g., the "b" part) because it
doesn't yet exist when you try to access it.

The more typical form of the problem is something like:

    global_var = 10

    def function():

       print global_var
       global_var = 20

Calling function() is also going to generate a NameError because the
assignment is used during compile time to make the variable local, but
then it hasn't yet been given a value before you get to the print.

See also http://www.python.org/doc/FAQ.html#4.36 and
http://www.python.org/doc/FAQ.html#4.57, and perhaps section 9.2 in
the Tutorial.

The fix in this case is to add "global global_var" to the function.
But that just tells Python that the variable should reference the
global namespace throughout the block.  In your case adding that would
make your code run without an exception, but I'm guessing it wouldn't
do what you want since your assignment would then change the global
'settings' after the first pass through the method.  I'm not sure (but
would guess not) that Python's scoping rules permit the sort of
example you have directly.

So I'd probably just pick a slightly different name.  Or
alternatively, one way around this would be to store a reference to
the global name when your class is created, and then reference that
within the method.  So for example, something like:

    class K:
	def __init__(self):
	    self.settings = settings

	def foo(self):
	    settings = self.settings['x']
    K().foo()

But that's still a little too many uses for the same name for my taste :-)

--
-- David
-- 
/-----------------------------------------------------------------------\
 \               David Bolen            \   E-mail: db3l at fitlinxx.com  /
  |             FitLinxx, Inc.            \  Phone: (203) 708-5192    |
 /  860 Canal Street, Stamford, CT  06902   \  Fax: (203) 316-5150     \
\-----------------------------------------------------------------------/



More information about the Python-list mailing list