Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between @classmethod and a method in python [duplicate]

Tags:

python

What is the difference between @classmethod and a 'classic' method in python,

When should I use the @classmethod and when should I use a 'classic' method in python. Is the classmethod must be an method who is referred to the class (I mean it's only a method who handle the class) ?

And I know what is the difference between a @staticmethod and classic method Thx

like image 308
Freelancer Avatar asked Jul 31 '13 08:07

Freelancer


People also ask

What does @classmethod mean in Python?

In Python, the @classmethod decorator is used to declare a method in the class as a class method that can be called using ClassName. MethodName() . The class method can also be called using an object of the class. The @classmethod is an alternative of the classmethod() function.

What is the difference between an attribute and a method?

A variable stored in an instance or class is called an attribute. A function stored in an instance or class is called a method.

What is the difference between @staticmethod and @classmethod in Python?

The static method does not take any specific parameter. 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.

What is __ method __ in Python?

__call__ method is used to use the object as a method. __iter__ method is used to generate generator objects using the object.


2 Answers

Let's assume you have a class Car which represents the Car entity within your system.

A classmethod is a method that works for the class Car not on one of any of Car's instances. The first parameter to a function decorated with @classmethod, usually called cls, is therefore the class itself. Example:

class Car(object):    
    colour = 'red'

    @classmethod
    def blue_cars(cls):
        # cls is the Car class
        # return all blue cars by looping over cls instances

A function acts on a particular instance of the class; the first parameter usually called self is the instance itself:

def get_colour(self):
    return self.colour

To sum up:

  1. use classmethod to implement methods that work on a whole class (and not on particular class instances):

    Car.blue_cars()
    
  2. use instance methods to implement methods that work on a particular instance:

    my_car = Car(colour='red')
    my_car.get_colour() # should return 'red'
    
like image 154
Joseph Victor Zammit Avatar answered Sep 22 '22 00:09

Joseph Victor Zammit


If you define a method inside a class, it is handled in a special way: access to it wraps it in a special object which modifies the calling arguments in order to include self, a reference to the referred object:

class A(object):
    def f(self):
        pass

a = A()
a.f()

This call to a.f actually asks f (via the descriptor protocol) for an object to really return. This object is then called without arguments and deflects the call to the real f, adding a in front.

So what a.f() really does is calling the original f function with (a) as arguments.

In order to prevent this, we can wrap the function

  1. with a @staticmethod decorator,
  2. with a @classmethod decorator,
  3. with one of other, similiar working, self-made decorators.

@staticmethod turns it into an object which, when asked, changes the argument-passing behaviour so that it matches the intentions about calling the original f:

class A(object):
    def method(self):
        pass
    @staticmethod
    def stmethod():
        pass
    @classmethod
    def clmethod(cls):
        pass

a = A()
a.method() # the "function inside" gets told about a
A.method() # doesn't work because there is no reference to the needed object
a.clmethod() # the "function inside" gets told about a's class, A
A.clmethod() # works as well, because we only need the classgets told about a's class, A
a.stmethod() # the "function inside" gets told nothing about anything
A.stmethod() # works as well

So @classmethod and @staticmethod have in common that they "don't care about" the concrete object they were called with; the difference is that @staticmethod doesn't want to know anything at all about it, while @classmethod wants to know its class.

So the latter gets the class object the used object is an instance of. Just replace self with cls in this case.

Now, when to use what?

Well, that is easy to handle:

  • If you have an access to self, you clearly need an instance method.
  • If you don't access self, but want to know about its class, use @classmethod. This may for example be the case with factory methods. datetime.datetime.now() is such an example: you can call it via its class or via an instance, but it creates a new instance with completely different data. I even used them once for automatically generating subclasses of a given class.
  • If you need neither self nor cls, you use @staticmethod. This can as well be used for factory methods, if they don't need to care about subclassing.
like image 41
glglgl Avatar answered Sep 18 '22 00:09

glglgl