In below example Test class has two instance method and one classmethod
In set_cls_var_1 method I set class variable using self.
In set_cls_var_2 method I call class method using self.
class Test():
#class variable
cls_var = 10
def __init__(self):
obj_var=20
def set_cls_var_1(self,val):
#second method to access class variable
print "first "
self.cls_var = val
def set_cls_var_2(self):
print "second"
self.task(200)
@classmethod
def task(cls,val):
cls.cls_var = val
t=Test()
#set class variable by first method
t.set_cls_var_1(100)
print Test.cls_var
#set class variable by second method
t.set_cls_var_2()
print Test.cls_var
Output
first
10
second
200
Expected Output
first
100
second
200
My question is: why only classmethod can call by self, Why not class variable
When you attempt to access an object's attribute using self
, Python first searches the object's attributes. If it cannot find it there, then is searches the object's class's attributes. That is what's happening in your case;
Python first searches t
's attributes. It doesn't find cls_var
, so it then searches the T
class's attributes. It finds cls_var
so it stops, and returns cls_var
's value.
However, when assigning attributes to self
, Python always assigns them directly to the object, and never the object's class unless explicitly told to do so. That's why assinging self.cls_var
to 100
didn't affect Test
's cls_var
attrbiute.
I find something else that always use following way to access classmethod or variable in instance method
class Test():
#class variable
cls_var = 10
def __init__(self):
obj_var=20
def set_cls_var_1(self,val):
#first method to access class variable
print "first type"
cls = self.__class__
cls.cls_var = val
t=Test()
#set class variable by first method
t.set_cls_var_1(100)
print Test.cls_var
When defining the Test class like you did, python creates a class object called Test which has an attribute cls_var
equal to 10. When you instantiate this class, the created object doesn't have cls_var
attribute. When calling self.cls_var
it is actually the class' attribute that is retrieved due to the way python resolves attributes.
However when set self.cls_var
the value is set at the object level! So further call to self.cls_var
will give you the value of the object's attribute, and not the class' anymore!
Maybe this bit of code will make this clearer:
class A(object):
a = 1
a = A()
print a.a # prints 1
A.a = 2
print a.a # prints 2
You see that even though when set the value at the class level, the changes are repercuted on the object, because, python will look up for the attribute in the class when it is not found at the object level.
When calling Test.cls_var
it is the cls_var
attribute of the class you are accessing! Not the one of the object you just modified.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With