I come from java background, so I am slightly confused here.
Consider the code snippet below:
class A():
def __init__(self, **kwargs):
self.obj_var = "I am obj var"
@classmethod
def class_method(cls):
print cls.obj_var # this line is in question here
cls.cls_obj = "I m class object"
return cls.cls_obj
This throws an error :
In [30]: a = A()
In [31]: a.obj_var
Out[31]: 'I am obj var'
In [32]: a.class_method()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-32-3dcd9d512548> in <module>()
----> 1 a.class_method()
<ipython-input-29-9c0d341ad75f> in class_method(cls)
8 @classmethod
9 def class_method(cls):
---> 10 print cls.obj_var
11 cls.cls_obj = "I m class object"
12 return cls.cls_obj
AttributeError: class A has no attribute 'obj_var'
iIf I comment out @classmethod
, this will work fine.
My understanding (which is incorrect m sure) :
When I do a = A()
, then all the variables(obj_var
) created in __init__
can be accessed via this a
when passed to any other classmethod
of same class.Apparently this is not the case.
Question(s)
why am i not able to access __init__
var
s in class_method
when decorater @classmethod
is mentioned in the method but on removing the decorater, it works fine?
how python internally process this particular class upon compilation?
is there any way i can use @classmethod
and the __init__
vars in same method?
A class method is a method which is bound to the class and not the object of the class. They have the access to the state of the class as it takes a class parameter that points to the class and not the object instance. It can modify a class state that would apply across all the instances of the class.
Class method can access and modify the class state. Static Method cannot access or modify the class state. The class method takes the class as parameter to know about the state of that class. Static methods do not know about class state.
Class methods can access class variables and class methods directly. Class methods cannot access instance variables or instance methods directly—they must use an object reference. Also, class methods cannot use the this keyword as there is no instance for this to refer to.
Class methods don't need a class instance. They can't access the instance ( self ) but they have access to the class itself via cls . Static methods don't have access to cls or self . They work like regular functions but belong to the class's namespace.
Let's talk about how Python's methods actually work.
You may have noticed that Python methods are declared just like free-standing functions, but inside a class. That's because Python methods really are free-standing functions that happen to be inside a class. The self
/cls
argument is not special. It's just the first argument of the function.
Before we go any further, I'd like to point out that you don't appear to be explicitly inheriting from object
. If you are working in Python 2.x, there is no object
at the root of the graph unless you explicitly inherit from it. That is a bad thing, and you should inherit directly or indirectly from object
whenever possible in new code. Inheriting from object
in Python 3 is legal and harmless, but unnecessary. The rest of this discussion assumes that you are either working in 3.x or have fixed this.
When you access a variable, function, method, or any other type of object with foo.bar
, certain hooks known as the "descriptor protocol" get invoked. You don't have to know the details of this to understand how functions work. All you have to know is this:
bar
directly attached to foo
(and foo
is not a class), we just return it directly.(*)foo
is a class and bar
is a @classmethod
function(**) declared either in foo
or in one of its superclasses, then the first argument is set to foo
before we return it. Otherwise, it is returned unchanged.(***) If we returned something, we stop here.foo
. This consists of foo
's class (known as type(foo)
), that class's superclass, and so on until we get to object
. In cases of multiple inheritance, this gets a little more complicated, but again, you don't need to know that.bar
variable from the first class which has one (call it Baz
).Baz.bar
is a regular, undecorated function, set its first argument to foo
and return it.Baz.bar
is a @classmethod
function, set its first argument to type(foo)
and return it.Baz.bar
is a @staticmethod
function, or not a function(**) at all, return it unchanged.As you can see, if the method is declared @classmethod
, the first argument is always the class, and never the instance, regardless of how the function is invoked. That means you don't have access to the instance variables of foo
, since you don't have access to foo
itself. Any variables set in __init__()
are instance variables, so they are not visible here.
And here are all the things I lied about:
(*): Python actually does the rest of this work first and then comes back to this step. But that only matters for things like @property
, which can actually override local instance variables. Regular methods cannot.
(**): This is a lie. Python also does special processing on @property
functions in this case, and on anything else that implements certain special methods.
(***): I am also ignoring unbound methods in Python 2.x because, aside from certain really weird cases (when you try to pass an object of the wrong type as the first argument by hand), they make no difference whatsoever. They do not exist in Python 3.
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