7

In Python, if I define a variable:

my_var = (1,2,3)

and try to access it in __init__ function of a class:

class MyClass:
    def __init__(self):
        print my_var

I can access it and print my_var without stating (global my_var).

If I put my_var right after class MyClass however, I get scope error (no global variable found).

What is the reason for this? How should I do this? Where can I read about this to learn? I did read Python Class page but I did not encounter its explanation.

Thank you

Phil
  • 13,875
  • 21
  • 81
  • 126

4 Answers4

12

Complementing @mgilson's answer: Note that Python Class variables are shared among the class instances. And the behaviour might be VERY unexpected and seem weird. In practice it works like this:

class MyClass(object):
    my_var = 10

    def __init__(self):
        print(self.my_var)


m1 = MyClass()
print(m1.my_var)
>>> 10          # this is fine

MyClass.my_var = 20
print(m1.my_var)
>>> 20          # WTF? :) --> shared value

m2 = MyClass()
print(m2.my_var)
>>> 20          # this is expected

m1.my_var = 30
print(MyClass.my_var)
>>> 20          # this is also expected

MyClass.my_var = 40 
print(m1.my_var)
>>> 30           # But WHY? Isn't it shared? --> 
                 # The value WAS shared until m1.my_var = 30 has happened.

print(m2.my_var)
>>> 40           # yep m2.my_var's value is still shared :)
Zaur Nasibov
  • 22,280
  • 12
  • 56
  • 83
  • BasicWolf, since @mgilson's answer was a bit more on the subject, I could not help but choose it as the correct answer. But I sincerely thank you so much for this excellent, truly great explanation. It made me understand a lot, on top of what mgilson clearified. Thanks a lot! – Phil Oct 17 '12 at 20:19
11

When you put it right after class MyClass, it becomes a class attribute and you can get access to it via MyClass.my_var or as self.my_var from within the class (provided you don't create an instance variable with the same name).

Here's a little demo:

my_var = 'global'
class MyClass(object):
   my_var = 'class' 
   def __init__(self):
      print my_var #global
      print MyClass.my_var #class
      print self.my_var #class -- Only since we haven't set this attribute on the instance
      self.my_var = 'instance' #set instance attribute.
      print self.my_var #instance
      print MyClass.my_var #class
mgilson
  • 300,191
  • 65
  • 633
  • 696
  • if you put it in `__init__`, this means that this is only initialized when an object is created. – ronak Oct 17 '12 at 19:20
  • @ronak -- I'm not sure I understand your comment. Care to elaborate? – mgilson Oct 17 '12 at 19:25
  • @mgilson: beware: in this case the first `print self.my_var" will print the class variable (containing (4,5,6), not (1,2,3). – jsbueno Oct 17 '12 at 19:32
  • While an instance attribute with the name `my_var` is not created, tries to access it will yield the class attribute instead - not the global variable. – jsbueno Oct 17 '12 at 19:34
  • @jsbueno -- I did run it beforehand -- the class variable is `(1,2,3)`, the global is `(4,5,6)`, I'm not sure I understand what you're saying ... – mgilson Oct 17 '12 at 19:35
  • Changed to use more meaningful data for the variables (to make it easier to track what is what) – mgilson Oct 17 '12 at 19:43
  • @mgilson I meant to say that if you use `my_var` in the class definition (right after `class MyClass`) then it is a class variable and if you include it in the `__init__` function, you will have to create an object to access that variable. You answer is correct and I gave you an upvote. – ronak Oct 17 '12 at 19:51
2

If you write:

class MyClass(object):
    my_var = (1, 2, 3)

you are defining an attribute of MyClass, not a variable. In your __init__ method, then, it is MyClass.my_var.

kindall
  • 178,883
  • 35
  • 278
  • 309
1

Once it's inside the class definition, it's no longer global, it's now in the class object's namespace. You can access it with self.my_var within __init__ though...

retracile
  • 12,167
  • 4
  • 35
  • 42