Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I use @classmethod and when def method(self)?

While integrating a Django app I have not used before, I found two different ways to define functions inside the class. The author seems to use them both distinctively and intentionally. The first one is the one that I myself use a lot:

class Dummy(object):      def some_function(self, *args, **kwargs):         # do something here         # self is the class instance 

The other one is the one I never use, mostly because I do not understand when and what to use it for:

class Dummy(object):      @classmethod     def some_function(cls, *args, **kwargs):         # do something here         # cls refers to what? 

The classmethod decorator in the python documentation says:

A class method receives the class as the implicit first argument, just like an instance method receives the instance.

So I guess cls refers to Dummy itself (the class, not the instance). I do not exactly understand why this exists, because I could always do this:

type(self).do_something_with_the_class 

Is this just for the sake of clarity, or did I miss the most important part: spooky and fascinating things that couldn't be done without it?

like image 374
marue Avatar asked May 14 '12 15:05

marue


People also ask

What is @classmethod used for?

The @classmethod decorator is a built-in function decorator which is an expression that gets evaluated after your function is defined. The result of that evaluation shadows your function definition. A class method receives the class as the implicit first argument, just like an instance method receives the instance.

When should I use Classmethod Python?

You can use class methods for any methods that are not bound to a specific instance but the class. In practice, you often use class methods for methods that create an instance of the class. When a method creates an instance of the class and returns it, the method is called a factory method.

What is the difference between @classmethod and @staticmethod decorators?

The difference between the Class method and the static method is: A class method takes cls as the first parameter while a static method needs no specific parameters. A class method can access or modify the class state while a static method can't access or modify it.

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.


1 Answers

Your guess is correct - you understand how classmethods work.

The why is that these methods can be called both on an instance OR on the class (in both cases, the class object will be passed as the first argument):

class Dummy(object):      @classmethod     def some_function(cls,*args,**kwargs):         print cls  #both of these will have exactly the same effect Dummy.some_function() Dummy().some_function() 

On the use of these on instances: There are at least two main uses for calling a classmethod on an instance:

  1. self.some_function() will call the version of some_function on the actual type of self, rather than the class in which that call happens to appear (and won't need attention if the class is renamed); and
  2. In cases where some_function is necessary to implement some protocol, but is useful to call on the class object alone.

The difference with staticmethod: There is another way of defining methods that don't access instance data, called staticmethod. That creates a method which does not receive an implicit first argument at all; accordingly it won't be passed any information about the instance or class on which it was called.

In [6]: class Foo(object): some_static = staticmethod(lambda x: x+1)  In [7]: Foo.some_static(1) Out[7]: 2  In [8]: Foo().some_static(1) Out[8]: 2  In [9]: class Bar(Foo): some_static = staticmethod(lambda x: x*2)  In [10]: Bar.some_static(1) Out[10]: 2  In [11]: Bar().some_static(1) Out[11]: 2 

The main use I've found for it is to adapt an existing function (which doesn't expect to receive a self) to be a method on a class (or object).

like image 133
Marcin Avatar answered Sep 23 '22 17:09

Marcin