So... There's a couple of concepts that you should probably clarify.
That global_var
is not a global variable. It's a class attribute. It means it's only defined once: When you declare the class. After that, all the classes of the same type (or their inherited classes) will share the same variable. I found this, which is probably helpful.
That means that all the instances of type A
or of any type inheriting from A
(namely B
in the example) that you create will share it. However, you still need to access them through self
or through the cls
(usually the class
instance is named like that in classmethods) What you're doing in this method...
def method_that_returns_global_var(self):
#do some operations on global_var
global_var=(.....some logic....)
... is just creating a global_var
variable local to the method_that_returns_global_var
method (and has nothing to do with the global_var
in the class)
If it helps you see it (it certainly helps me), you can think of that global_var
as attached to the class
, not to the instances of that class.
This means that class B
already has access to global_var
because it inherits from A
. When you try to access global_var
in an instance method (the ones that you pass self
to, broadly speaking), what the interpreter is gonna try to do is find the global_var
attribute among the ones of the instance (self
). If it doesn't find it it will go to the class. However (very important) when you assign in an instance method (you do self.global_var = whatever
), the interpreter will just place global_var
in the instance (in its "internal" dictionary of attributes __dict__
) Don't let that confuse you!
See this:
class A(object):
global_var = 5
def some_function(self):
return self.global_var + 2
def print_global_bar(self):
print("Global bar value=%s" % self.global_var)
class B(A):
def method_that_returns_global_var(self):
# do some operations on global_var
self.global_var = 1000
return self.global_var
if __name__ == "__main__":
b = B()
b.print_global_bar()
b.method_that_returns_global_var()
b.print_global_bar()
print("Because `method_that_returns_global_var` does an ASSIGNMENT, now I have two `global_var`."
" One in the class, one in the instance `b`")
print("In the instance: %s" % b.global_var)
print("In the class: %s" % b.__class__.global_var)
It outputs:
Global bar value=5
Global bar value=1000
Because `method_that_returns_global_var` does an ASSIGNMENT, now I have two `global_var`. One in the class, one in the instance `b`
In the instance: 1000
In the class: 5
If you wanted to do the assignment to the class variable in method_that_returns_global_var
you should either do it a class method (with the @classmethod
decorator) or access the class of the instance (located in self.__class__
)
See now:
class A(object):
global_var = 5
def some_function(self):
return self.global_var + 2
def print_global_bar(self):
print("Global bar value=%s" % self.global_var)
class B(A):
def method_that_returns_global_var(self):
# do some operations on global_var
self.__class__.global_var = 1000
return self.global_var
if __name__ == "__main__":
b = B()
b.print_global_bar()
b.method_that_returns_global_var()
b.print_global_bar()
print("In the instance: %s" % b.global_var)
print("In the class: %s" % b.__class__.global_var)
Outputs:
Global bar value=5
Global bar value=1000
In the instance: 1000
In the class: 1000
See the difference? In the first method, doing self.global_var = 1000
creates a new attribute in the instance, disregarding whatever is written in the class
. Basically, you have two global_var
s around: One connected to the class (whose value is still 5
), and one connected to the instance (whose value is 1000
). In the second method, you are accessing and modifying all the time the class variable (A.global_var
)
I recommend you play a bit more with this... More print
s, more .__class__
... things like that. :-)