tags:

views:

533

answers:

2

Apologies, somewhat confused Python newbie question. Let's say I have a module called animals.py.......

globvar = 1

class dog: 
   def bark(self):
      print globvar

class cat:
   def miaow(self):
      print globvar

What is the difference between this and

class dog:
   def __init__(self):
      global globvar

   def bark(self):
      print globvar

class cat:
   def miaow(self):
      print globvar

Assuming I always instantiate a dog first?

I guess my question is, is there any difference? In the second example, does initiating the dog create a module level globvar just like in the first example, that will behave the same and have the same scope?

+3  A: 

No, the global statement only matters when you're assigning to a global variable within a method or function. So that __init__ is irrelevant -- it does not create the global, because it's not assigning anything to it.

Alex Martelli
Except that cat class will return an error, right Alex, if a dog hasn't been instantiated first? If I don't have the global globvar statement in the dog's __init__ then cat returns an error. But otherwise the scope of the two is identical. Thanks for help.
In your second example, you will always get an error because you never created globvar. The "global" keyword does not create a global variable. What the global statement does is tell Python that you are referring to a global variable, and not creating a new, separate local variable that has the same name. As Alex said, this only matters when you are assigning a value to a global variable from within a method or function.
htw
@Thomas, @htw is exactly correct: to make it work as you think it should, that __init__ requires an assignment to globvar (and _then_ it will fail if you instantiate a cat before a dog).
Alex Martelli
Thanks htw and Alex. I guess my old Pascal/c experience (rusty!) thinking got me to believe "global globvar" declared a variable. classic error of a newbie Pythonista still living in the old paradigm. I consider myself enlightend.
+4  A: 

global doesn't create a new variable, it just states that this name should refer to a global variable instead of a local one. Usually assignments to variables in a function/class/... refer to local variables. For example take a function like this:

def increment(n)
  # this creates a new local m
  m = n+1
  return m

Here a new local variable m is created, even if there might be a global variable m already existing. This is what you usually want since some function call shouldn't unexpectedly modify variables in the surrounding scopes. If you indeed want to modify a global variable and not create a new local one, you can use the global keyword:

def increment(n)
  global increment_calls
  increment_calls += 1
  return n+1

In your case global in the constructor doesn't create any variables, further attempts to access globvar fail:

>>> import animals
>>> d = animals.dog()
>>> d.bark()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "animals.py", line 7, in bark
    print globvar
NameError: global name 'globvar' is not defined

But if you would actually assign a value to globvar in the constructor, a module-global variable would be created when you create a dog:

class dog:
   def __init__(self):
      global globvar
      globvar = 1
...

Execution:

>>> import animals
>>> d = animals.dog()
>>> d.bark()
1
>>> print animals.globvar
1
sth
Class stuff, sth. Thank you. Perfectly answers the question