Should this method be a classmethod and why can't it access vars?

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:

  1. First, if there's an instance variable bar directly attached to foo (and foo is not a class), we just return it directly.(*)
  2. If 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.
  3. We search the "method resolution order" of 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.
  4. Take the bar variable from the first class which has one (call it Baz).
  5. If Baz.bar is a regular, undecorated function, set its first argument to foo and return it.
  6. Otherwise, if Baz.bar is a @classmethod function, set its first argument to type(foo) and return it.
  7. Otherwise, if 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 want to access an instance variable from a class method you need to create an instance of the class where the instance variable is present. Hope below code should work.

class A():
def __init__(self, **kwargs):
    self.obj_var = "I am obj var"

@classmethod
def class_method(cls):
    self = cls() # Here you are creating an instance of the class (in this case it is class A)
    print(self.obj_var) 
    cls.cls_obj = "I m class object"
    return cls.cls_obj

 print(A.class_method())