2

I am currently learning Python. in OOP what is the purpose of @classmethod decorator? What is the difference accessing class variables via @classmethod and accessing it through just normal method? Like I can do that same like this:

class A():
   _variable = A

   def getVariable(self):
      return self._variable 
 

or

class A():
   _variable = A

   @classmethod
   def getVariable(cls):
      return cls._variable 
 

What is the difference between both methods? Why do I need to use when do I use the classmethod and when do I not have to? And what happens if I don't?

m02ph3u5
  • 3,022
  • 7
  • 38
  • 51
  • 1
    I recommend these as well: [Meaning of classmethod and staticmethod for beginner?](https://stackoverflow.com/questions/12179271/meaning-of-classmethod-and-staticmethod-for-beginner) and [Difference between staticmethod and classmethod](https://stackoverflow.com/questions/136097/difference-between-staticmethod-and-classmethod) – salyangoz Oct 23 '20 at 08:23
  • Please fix your formatting: proper indentation is crucial in Python. – Roel Schroeven Oct 23 '20 at 08:33

2 Answers2

3

When using class and instance variables/methods what you care is visibility!

A class variable/method is shared by all the instances of the class while the instance variable/method is only available to the instance you have right now!

Generally speaking, instance variables are for data unique to each instance and class variables are for attributes and methods shared by all instances of the class: python tutorial

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance

>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind                  # shared by all dogs
'canine'
>>> e.kind                  # shared by all dogs
'canine'
>>> d.name                  # unique to d
'Fido'
>>> e.name                  # unique to e
'Buddy'

What this example is not showing you is that with a class method you can call the method on the class without going through an instance!

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance

    @classmethod
    def isGoodBoy(cls):
        return True  # all dogs are good boys!

Now the isGoodBoy method does not need to access the name of the dog, so it can be a class method and this reflects on all instances; after all all dogs are good boys (and gals!).

But this tells you more! is a dog a good boy? Are we asking for any specific dog to be a good boy?

>> Dog.isGoodBoy() # here we call the method on the class
True # debate settled!

Now four your other questions; it's good practice to have a class method when you do work on classes, not objects. How do you know if an instance of a logger requires the network before creating it? That's what class methods and class variables are for, along with having common state and behavior for all objects of that class.

Now as this is shared between all classes you now have other problems, each instance of the class might modify the class variable! This also means that you can query the variable value without an object!

Say you want to switch from method A to method B while running.


class Foo:
    upgrade = False
    def a(self):
        ...
    def b(self):
        ...
    def run(self):
        self.a() if self.upgrade else self.b()

Now a Foo.upgrade = True will switch stuff for everybody! Or even better make a dog a feline by running Dog.kind = 'feline'

edoput
  • 1,212
  • 9
  • 17
1

@classmethod defines that the following method is static and belongs to the class and not the object.

So a method with @classmethod can't access any values of an object, but it can be called without initializing a object of that class.

An use case would be:

class Test:
    @classmethod
    def foo(cls, a, b):
        # do smth

Test.foo(1, "abc")
Stefan xyz
  • 21
  • 1
  • "static" methods are something else. A `@classmethod` always expects the class object as the first parameter. A `@staticmethod` does not. – NeilG Mar 02 '23 at 05:44